diff --git a/bizmatch-server/.editorconfig b/bizmatch-server/.editorconfig
new file mode 100644
index 0000000..59d9a3a
--- /dev/null
+++ b/bizmatch-server/.editorconfig
@@ -0,0 +1,16 @@
+# Editor configuration, see https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.ts]
+quote_type = single
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/bizmatch-server/.eslintrc.json b/bizmatch-server/.eslintrc.json
new file mode 100644
index 0000000..eb7cda9
--- /dev/null
+++ b/bizmatch-server/.eslintrc.json
@@ -0,0 +1,45 @@
+{
+ "env": {
+ "es2021": true,
+ "browser": true
+ },
+ "extends": [
+ "airbnb-base",
+ "airbnb-typescript",
+ "plugin:@typescript-eslint/recommended",
+ "eslint-config-prettier",
+ "plugin:cypress/recommended"
+ ],
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "ecmaVersion": 12,
+ "sourceType": "module",
+ "project": ["./tsconfig.json"]
+ },
+ "plugins": ["@typescript-eslint"],
+ "rules": {
+ "import/no-unresolved": ["off"],
+ "import/prefer-default-export": ["off"],
+ "no-useless-constructor": "off",
+ "@typescript-eslint/no-useless-constructor": ["error"],
+ "@typescript-eslint/lines-between-class-members": ["off"],
+ "no-param-reassign": ["off"],
+ "max-classes-per-file": ["off"],
+ "no-shadow": ["off"],
+ "class-methods-use-this": ["off"],
+ "react/jsx-filename-extension": ["off"],
+ "import/no-cycle": ["off"],
+ "radix": ["off"],
+ "no-promise-executor-return": ["off"],
+ "@typescript-eslint/naming-convention": [
+ "error",
+ {
+ "selector": "enumMember",
+ "format": ["UPPER_CASE", "PascalCase"]
+ }
+ ],
+ "no-restricted-syntax": ["error", "ForInStatement", "LabeledStatement", "WithStatement"],
+ "spaced-comment": ["off"],
+ "import/no-extraneous-dependencies": ["error", { "devDependencies": true }]
+ }
+ }
\ No newline at end of file
diff --git a/bizmatch-server/.prettierrc b/bizmatch-server/.prettierrc
index dcb7279..9c49078 100644
--- a/bizmatch-server/.prettierrc
+++ b/bizmatch-server/.prettierrc
@@ -1,4 +1,18 @@
{
+ "arrowParens": "avoid",
+ "embeddedLanguageFormatting": "auto",
+ "htmlWhitespaceSensitivity": "css",
+ "insertPragma": false,
+ "jsxBracketSameLine": false,
+ "jsxSingleQuote": false,
+ "printWidth": 220,
+ "proseWrap": "always",
+ "quoteProps": "as-needed",
+ "requirePragma": false,
+ "semi": true,
"singleQuote": true,
- "trailingComma": "all"
+ "tabWidth": 2,
+ "trailingComma": "all",
+ "useTabs": false,
+ "vueIndentScriptAndStyle": false
}
\ No newline at end of file
diff --git a/bizmatch-server/.vscode/settings.json b/bizmatch-server/.vscode/settings.json
new file mode 100644
index 0000000..0fd6e04
--- /dev/null
+++ b/bizmatch-server/.vscode/settings.json
@@ -0,0 +1,28 @@
+{
+ "editor.suggestSelection": "first",
+ "vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
+ "explorer.confirmDelete": false,
+ "typescript.updateImportsOnFileMove.enabled": "always",
+ "[typescript]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[html]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[json]": {
+ "editor.defaultFormatter": "vscode.json-language-features"
+ },
+ "[scss]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[jsonc]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "editor.formatOnSave": true,
+ "editor.codeActionsOnSave": {
+ "source.organizeImports": "explicit"
+ },
+ "prettier.printWidth": 240,
+ "git.autofetch": false,
+ "git.autorefresh": true
+}
diff --git a/bizmatch-server/data/broker.json b/bizmatch-server/data/broker.json
index 71c2bd9..ec3cace 100644
--- a/bizmatch-server/data/broker.json
+++ b/bizmatch-server/data/broker.json
@@ -27,7 +27,8 @@
"Bexar County, TX",
"Travis County, TX"
],
- "offeredServices": "
Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
",
+ "gender": "male"
},
{
"id": "1s2t3u4v-5w6x-7y8z-9a0b-1c2d3e4f5g6h",
@@ -55,7 +56,8 @@
"Bastrop County, TX",
"Caldwell County, TX"
],
- "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
"
+ "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
",
+ "gender":"female"
},
{
"id": "7i8j9k0l-1m2n-3o4p-5q6r-7s8t9u0v1w2x",
@@ -83,7 +85,8 @@
"Kendall County, TX",
"Medina County, TX"
],
- "offeredServices": "Services Offered
- Business valuation
- Marketing and advertising
- Buyer screening and qualification
- Negotiations and deal structuring
- Due diligence coordination
- Closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Marketing and advertising
- Buyer screening and qualification
- Negotiations and deal structuring
- Due diligence coordination
- Closing support
",
+ "gender":"male"
},
{
"id": "3y4z5a6b-7c8d-9e0f-1g2h-3i4j5k6l7m8n",
@@ -111,7 +114,8 @@
"Brazoria County, TX",
"Galveston County, TX"
],
- "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
",
+ "gender":"female"
},
{
"id": "9o0p1q2r-3s4t-5u6v-7w8x-9y0z1a2b3c4d",
@@ -139,7 +143,8 @@
"Denton County, TX",
"Johnson County, TX"
],
- "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
",
+ "gender":"male"
},
{
"id": "5e6f7g8h-9i0j-1k2l-3m4n-5o6p7q8r9s0t",
@@ -167,7 +172,8 @@
"Cherokee County, TX",
"Rusk County, TX"
],
- "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
"
+ "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
",
+ "gender":"female"
},
{
"id": "1u2v3w4x-5y6z-7a8b-9c0d-1e2f3g4h5i6j",
@@ -195,7 +201,8 @@
"Terry County, TX",
"Lynn County, TX"
],
- "offeredServices": "Services Offered
- Business valuation
- Marketing and advertising
- Buyer screening and qualification
- Negotiations and deal structuring
- Due diligence coordination
- Closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Marketing and advertising
- Buyer screening and qualification
- Negotiations and deal structuring
- Due diligence coordination
- Closing support
",
+ "gender":"male"
},
{
"id": "7k8l9m0n-1o2p-3q4r-5s6t-7u8v9w0x1y2z",
@@ -223,7 +230,8 @@
"Willacy County, TX",
"Zapata County, TX"
],
- "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
",
+ "gender":"female"
},
{
"id": "3a4b5c6d-7e8f-9g0h-1i2j-3k4l5m6n7o8p",
@@ -251,7 +259,8 @@
"Jeff Davis County, TX",
"Presidio County, TX"
],
- "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
",
+ "gender":"male"
},
{
"id": "9q0r1s2t-3u4v-5w6x-7y8z-9a0b1c2d3e4f",
@@ -279,7 +288,8 @@
"Bryan County, OK",
"Marshall County, OK"
],
- "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
"
+ "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
",
+ "gender":"female"
},
{
"id": "8a2b1c5d-7e6f-4g3h-9i1j-2k3l4m5n6o7p",
@@ -311,7 +321,8 @@
"Clark County, NV",
"Washoe County, NV"
],
- "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
",
+ "gender":"female"
},
{
"id": "4q5r6s7t-8u9v-0w1x-2y3z-4a5b6c7d8e9f",
@@ -339,7 +350,8 @@
"Brevard County, FL",
"Volusia County, FL"
],
- "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
"
+ "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
",
+ "gender":"male"
},
{
"id": "1g2h3i4j-5k6l-7m8n-9o0p-1q2r3s4t5u6v",
@@ -373,7 +385,8 @@
"Bergen County, NJ",
"Essex County, NJ"
],
- "offeredServices": "Services Offered
- Business valuation
- Marketing and advertising
- Buyer screening and qualification
- Negotiations and deal structuring
- Due diligence coordination
- Closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Marketing and advertising
- Buyer screening and qualification
- Negotiations and deal structuring
- Due diligence coordination
- Closing support
",
+ "gender":"female"
},
{
"id": "7w8x9y0z-1a2b-3c4d-5e6f-7g8h9i0j1k2l",
@@ -401,7 +414,8 @@
"Bexar County, TX",
"Travis County, TX"
],
- "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
",
+ "gender":"male"
},
{
"id": "3m4n5o6p-7q8r-9s0t-1u2v-3w4x5y6z7a8b",
@@ -433,7 +447,8 @@
"Milwaukee County, WI",
"Dane County, WI"
],
- "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
",
+ "gender":"female"
},
{
"id": "5g6h7i8j-9k0l-1m2n-3o4p-5q6r7s8t9u0v",
@@ -465,7 +480,8 @@
"Harris County, TX",
"Dallas County, TX"
],
- "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
",
+ "gender":"male"
},
{
"id": "1w2x3y4z-5a6b-7c8d-9e0f-1g2h3i4j5k6l",
@@ -493,7 +509,8 @@
"Doña Ana County, NM",
"San Juan County, NM"
],
- "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
"
+ "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
",
+ "gender":"female"
},
{
"id": "7m8n9o0p-1q2r-3s4t-5u6v-7w8x9y0z1a2b",
@@ -521,7 +538,8 @@
"Logan County, OK",
"Pottawatomie County, OK"
],
- "offeredServices": "Services Offered
- Business valuation
- Marketing and advertising
- Buyer screening and qualification
- Negotiations and deal structuring
- Due diligence coordination
- Closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Marketing and advertising
- Buyer screening and qualification
- Negotiations and deal structuring
- Due diligence coordination
- Closing support
",
+ "gender":"male"
},
{
"id": "3c4d5e6f-7g8h-9i0j-1k2l-3m4n5o6p7q8r",
@@ -549,7 +567,8 @@
"Garland County, AR",
"Washington County, AR"
],
- "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
",
+ "gender":"female"
},
{
"id": "9s0t1u2v-3w4x-5y6z-7a8b-9c0d1e2f3g4h",
@@ -577,7 +596,8 @@
"DeSoto County, MS",
"Harrison County, MS"
],
- "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
",
+ "gender":"male"
},
{
"id": "5i6j7k8l-9m0n-1o2p-3q4r-5s6t7u8v9w0x",
@@ -605,7 +625,8 @@
"Yavapai County, AZ",
"Mohave County, AZ"
],
- "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
"
+ "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
",
+ "gender":"female"
},
{
"id": "1y2z3a4b-5c6d-7e8f-9g0h-1i2j3k4l5m6n",
@@ -633,7 +654,8 @@
"Madison County, AL",
"Mobile County, AL"
],
- "offeredServices": "Services Offered
- Business valuation
- Marketing and advertising
- Buyer screening and qualification
- Negotiations and deal structuring
- Due diligence coordination
- Closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Marketing and advertising
- Buyer screening and qualification
- Negotiations and deal structuring
- Due diligence coordination
- Closing support
",
+ "gender":"male"
},
{
"id": "7o8p9q0r-1s2t-3u4v-5w6x-7y8z9a0b1c2d",
@@ -661,7 +683,8 @@
"DeKalb County, GA",
"Chatham County, GA"
],
- "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
",
+ "gender":"female"
},
{
"id": "3e4f5g6h-7i8j-9k0l-1m2n-3o4p5q6r7s8t",
@@ -693,7 +716,8 @@
"St. Tammany Parish, LA",
"Jefferson Parish, LA"
],
- "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
"
+ "offeredServices": "Services Offered
- Business valuation
- Market analysis
- Buyer and seller representation
- Due diligence assistance
- Negotiations and closing support
",
+ "gender":"male"
},
{
"id": "9u0v1w2x-3y4z-5a6b-7c8d-9e0f1g2h3i4j",
@@ -721,7 +745,8 @@
"Creek County, OK",
"Osage County, OK"
],
- "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
"
+ "offeredServices": "Services Offered
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
",
+ "gender":"female"
},
{
"id": "5k6l7m8n-9o0p-1q2r-3s4t-5u6v7w8x9y0z",
@@ -749,7 +774,8 @@
"Brazoria County, TX",
"Galveston County, TX"
],
- "offeredServices": "- Comprehensive business valuation
- Targeted marketing and advertising
- Thorough buyer screening and qualification
- Skilled negotiations and deal structuring
- Detailed due diligence coordination
- Professional closing support
"
+ "offeredServices": "- Comprehensive business valuation
- Targeted marketing and advertising
- Thorough buyer screening and qualification
- Skilled negotiations and deal structuring
- Detailed due diligence coordination
- Professional closing support
",
+ "gender":"male"
},
{
"id": "1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p",
@@ -777,7 +803,8 @@
"Sierra County, NM",
"Grant County, NM"
],
- "offeredServices": "What We Offer
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
"
+ "offeredServices": "What We Offer
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
",
+ "gender":"female"
},
{
"id": "7q8r9s0t-1u2v-3w4x-5y6z-7a8b9c0d1e2f",
@@ -805,7 +832,8 @@
"Carroll County, AR",
"Boone County, AR"
],
- "offeredServices": "- Comprehensive business valuation services
- Detailed market analysis
- Dedicated buyer and seller representation
- Thorough due diligence assistance
- Skilled negotiations and closing support
"
+ "offeredServices": "- Comprehensive business valuation services
- Detailed market analysis
- Dedicated buyer and seller representation
- Thorough due diligence assistance
- Skilled negotiations and closing support
",
+ "gender":"female"
},
{
"id": "3g4h5i6j-7k8l-9m0n-1o2p-3q4r5s6t7u8v",
@@ -833,7 +861,8 @@
"Union County, MS",
"Tate County, MS"
],
- "offeredServices": "Our Services Include
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
"
+ "offeredServices": "Our Services Include
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
",
+ "gender":"male"
},
{
"id": "9w0x1y2z-3a4b-5c6d-7e8f-9g0h1i2j3k4l",
@@ -861,7 +890,8 @@
"Vermilion Parish, LA",
"St. Landry Parish, LA"
],
- "offeredServices": "- Comprehensive business valuation
- Targeted marketing and advertising
- Thorough buyer screening and qualification
- Skilled negotiations and deal structuring
- Detailed due diligence coordination
- Professional closing support
"
+ "offeredServices": "- Comprehensive business valuation
- Targeted marketing and advertising
- Thorough buyer screening and qualification
- Skilled negotiations and deal structuring
- Detailed due diligence coordination
- Professional closing support
",
+ "gender":"female"
},
{
"id": "5m6n7o8p-9q0r-1s2t-3u4v-5w6x7y8z9a0b",
@@ -889,7 +919,8 @@
"Apache County, AZ",
"Mohave County, AZ"
],
- "offeredServices": "Services We Provide
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
"
+ "offeredServices": "Services We Provide
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
",
+ "gender":"male"
},
{
"id": "1c2d3e4f-5g6h-7i8j-9k0l-1m2n3o4p5q6r",
@@ -917,7 +948,8 @@
"Monroe County, AL",
"Clarke County, AL"
],
- "offeredServices": "- Comprehensive business valuation services
- Detailed market analysis
- Dedicated buyer and seller representation
- Thorough due diligence assistance
- Skilled negotiations and closing support
"
+ "offeredServices": "- Comprehensive business valuation services
- Detailed market analysis
- Dedicated buyer and seller representation
- Thorough due diligence assistance
- Skilled negotiations and closing support
",
+ "gender":"female"
},
{
"id": "7s8t9u0v-1w2x-3y4z-5a6b-7c8d9e0f1g2h",
@@ -945,7 +977,8 @@
"McIntosh County, GA",
"Bryan County, GA"
],
- "offeredServices": "What We Offer
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
"
+ "offeredServices": "What We Offer
- Business valuation
- Market analysis
- Buyer search and qualification
- Due diligence coordination
- Financing assistance
- Closing support
",
+ "gender":"male"
},
{
"id": "3i4j5k6l-7m8n-9o0p-1q2r-3s4t5u6v7w8x",
@@ -973,7 +1006,8 @@
"McClain County, OK",
"Pottawatomie County, OK"
],
- "offeredServices": "- Comprehensive business valuation
- Targeted marketing and advertising
- Thorough buyer screening and qualification
- Skilled negotiations and deal structuring
- Detailed due diligence coordination
- Professional closing support
"
+ "offeredServices": "- Comprehensive business valuation
- Targeted marketing and advertising
- Thorough buyer screening and qualification
- Skilled negotiations and deal structuring
- Detailed due diligence coordination
- Professional closing support
",
+ "gender":"female"
},
{
"id": "9y0z1a2b-3c4d-5e6f-7g8h-9i0j1k2l3m4n",
@@ -1001,7 +1035,8 @@
"Los Alamos County, NM",
"Sandoval County, NM"
],
- "offeredServices": "Services We Provide
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
"
+ "offeredServices": "Services We Provide
- Business listings
- Buyer search and qualification
- Due diligence support
- Financing assistance
- Closing coordination
",
+ "gender":"male"
},
{
"id": "5s6t7u8v-9w0x-1y2z-3a4b-5c6d7e8f9g0h",
@@ -1033,7 +1068,8 @@
"Clark County, NV",
"Washoe County, NV"
],
- "offeredServices": "Our Services
- Comprehensive business valuation
- Targeted marketing and advertising
- Extensive buyer network
- Thorough due diligence coordination
- Skilled negotiations and deal structuring
- Professional closing support
"
+ "offeredServices": "Our Services
- Comprehensive business valuation
- Targeted marketing and advertising
- Extensive buyer network
- Thorough due diligence coordination
- Skilled negotiations and deal structuring
- Professional closing support
",
+ "gender":"male"
},
{
"id": "1i2j3k4l-5m6n-7o8p-9q0r-1s2t3u4v5w6x",
@@ -1065,7 +1101,8 @@
"Orleans Parish, LA",
"Jefferson Parish, LA"
],
- "offeredServices": "- Comprehensive business valuation services
- Targeted marketing and advertising campaigns
- Extensive buyer database
- Thorough due diligence assistance
- Skilled negotiations and closing support
"
+ "offeredServices": "- Comprehensive business valuation services
- Targeted marketing and advertising campaigns
- Extensive buyer database
- Thorough due diligence assistance
- Skilled negotiations and closing support
",
+ "gender":"female"
},
{
"id": "7y8z9a0b-1c2d-3e4f-5g6h-7i8j9k0l1m2n",
@@ -1097,7 +1134,8 @@
"Fulton County, GA",
"Gwinnett County, GA"
],
- "offeredServices": "What We Offer
- Comprehensive business valuation
- Targeted marketing and advertising
- Extensive buyer network
- Thorough due diligence coordination
- Skilled negotiations and deal structuring
- Professional closing support
"
+ "offeredServices": "What We Offer
- Comprehensive business valuation
- Targeted marketing and advertising
- Extensive buyer network
- Thorough due diligence coordination
- Skilled negotiations and deal structuring
- Professional closing support
",
+ "gender":"male"
},
{
"id": "3o4p5q6r-7s8t-9u0v-1w2x-3y4z5a6b7c8d",
@@ -1129,7 +1167,8 @@
"Hudson County, NJ",
"Bergen County, NJ"
],
- "offeredServices": "- Comprehensive business valuation services
- Targeted marketing and advertising campaigns
- Extensive buyer database
- Thorough due diligence assistance
- Skilled negotiations and closing support
"
+ "offeredServices": "- Comprehensive business valuation services
- Targeted marketing and advertising campaigns
- Extensive buyer database
- Thorough due diligence assistance
- Skilled negotiations and closing support
",
+ "gender":"female"
},
{
"id": "9e0f1g2h-3i4j-5k6l-7m8n-9o0p1q2r3s4t",
@@ -1161,7 +1200,8 @@
"Milwaukee County, WI",
"Dane County, WI"
],
- "offeredServices": "Services We Provide
- Comprehensive business valuation
- Targeted marketing and advertising
- Extensive buyer network
- Thorough due diligence coordination
- Skilled negotiations and deal structuring
- Professional closing support
"
+ "offeredServices": "Services We Provide
- Comprehensive business valuation
- Targeted marketing and advertising
- Extensive buyer network
- Thorough due diligence coordination
- Skilled negotiations and deal structuring
- Professional closing support
",
+ "gender":"female"
},
{
"id": "5u6v7w8x-9y0z-1a2b-3c4d-5e6f7g8h9i0j",
@@ -1193,7 +1233,8 @@
"Multnomah County, OR",
"Washington County, OR"
],
- "offeredServices": "Our Services
- Comprehensive business valuation
- Targeted marketing and advertising
- Extensive buyer network
- Thorough due diligence coordination
- Skilled negotiations and deal structuring
- Professional closing support
"
+ "offeredServices": "Our Services
- Comprehensive business valuation
- Targeted marketing and advertising
- Extensive buyer network
- Thorough due diligence coordination
- Skilled negotiations and deal structuring
- Professional closing support
",
+ "gender":"male"
},
{
"id": "1k2l3m4n-5o6p-7q8r-9s0t-1u2v3w4x5y6z",
@@ -1225,7 +1266,8 @@
"Doña Ana County, NM",
"Santa Fe County, NM"
],
- "offeredServices": "- Comprehensive business valuation services
- Targeted marketing and advertising campaigns
- Extensive buyer database
- Thorough due diligence assistance
- Skilled negotiations and closing support
"
+ "offeredServices": "- Comprehensive business valuation services
- Targeted marketing and advertising campaigns
- Extensive buyer database
- Thorough due diligence assistance
- Skilled negotiations and closing support
",
+ "gender":"female"
},
{
"id": "7a8b9c0d-1e2f-3g4h-5i6j-7k8l9m0n1o2p",
@@ -1257,7 +1299,8 @@
"Salt Lake County, UT",
"Utah County, UT"
],
- "offeredServices": "What We Offer
- Comprehensive business valuation
- Targeted marketing and advertising
- Extensive buyer network
- Thorough due diligence coordination
- Skilled negotiations and deal structuring
- Professional closing support
"
+ "offeredServices": "What We Offer
- Comprehensive business valuation
- Targeted marketing and advertising
- Extensive buyer network
- Thorough due diligence coordination
- Skilled negotiations and deal structuring
- Professional closing support
",
+ "gender":"male"
},
{
"id": "3q4r5s6t-7u8v-9w0x-1y2z-3a4b5c6d7e8f",
@@ -1289,7 +1332,8 @@
"Cuyahoga County, OH",
"Franklin County, OH"
],
- "offeredServices": "- Comprehensive business valuation services
- Targeted marketing and advertising campaigns
- Extensive buyer database
- Thorough due diligence assistance
- Skilled negotiations and closing support
"
+ "offeredServices": "- Comprehensive business valuation services
- Targeted marketing and advertising campaigns
- Extensive buyer database
- Thorough due diligence assistance
- Skilled negotiations and closing support
",
+ "gender":"female"
},
{
"id": "9g0h1i2j-3k4l-5m6n-7o8p-9q0r1s2t3u4v",
@@ -1321,6 +1365,7 @@
"Greenville County, SC",
"Charleston County, SC"
],
- "offeredServices": "Services We Provide
- Comprehensive business valuation
- Targeted marketing and advertising
- Extensive buyer network
- Thorough due diligence coordination
- Skilled negotiations and deal structuring
- Professional closing support
"
+ "offeredServices": "Services We Provide
- Comprehensive business valuation
- Targeted marketing and advertising
- Extensive buyer network
- Thorough due diligence coordination
- Skilled negotiations and deal structuring
- Professional closing support
",
+ "gender":"female"
}
]
\ No newline at end of file
diff --git a/bizmatch-server/nest-cli.json b/bizmatch-server/nest-cli.json
index 1fe4736..ea67053 100644
--- a/bizmatch-server/nest-cli.json
+++ b/bizmatch-server/nest-cli.json
@@ -4,7 +4,10 @@
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true,
- "assets": ["assets/**/*","**/*.hbs"],
- "watchAssets": true
+ "assets": [
+ "assets/**/*",
+ "**/*.hbs"
+ ],
+ "watchAssets": true
}
-}
+}
\ No newline at end of file
diff --git a/bizmatch-server/package.json b/bizmatch-server/package.json
index 7dcf006..3a96b6a 100644
--- a/bizmatch-server/package.json
+++ b/bizmatch-server/package.json
@@ -83,6 +83,7 @@
"kysely-codegen": "^0.15.0",
"pg-to-ts": "^4.1.1",
"prettier": "^3.0.0",
+ "rimraf": "^5.0.5",
"source-map-support": "^0.5.21",
"supertest": "^6.3.3",
"ts-jest": "^29.1.0",
diff --git a/bizmatch-server/src/drizzle/import.ts b/bizmatch-server/src/drizzle/import.ts
index f2ae6fa..1f3a744 100644
--- a/bizmatch-server/src/drizzle/import.ts
+++ b/bizmatch-server/src/drizzle/import.ts
@@ -1,15 +1,17 @@
import 'dotenv/config';
import { drizzle } from 'drizzle-orm/node-postgres';
+import { existsSync, readFileSync, readdirSync, statSync, unlinkSync } from 'fs';
+import { join } from 'path';
import pkg from 'pg';
-const { Pool } = pkg;
-import * as schema from './schema.js';
-import { readFileSync } from 'fs';
+import { rimraf } from 'rimraf';
+import sharp from 'sharp';
import { BusinessListing, CommercialPropertyListing, User } from 'src/models/db.model.js';
+import * as schema from './schema.js';
+const { Pool } = pkg;
-
-const connectionString = process.env.DATABASE_URL
+const connectionString = process.env.DATABASE_URL;
// const pool = new Pool({connectionString})
-const client = new Pool({ connectionString })
+const client = new Pool({ connectionString });
const db = drizzle(client, { schema, logger: true });
//Delete Content
@@ -18,60 +20,134 @@ await db.delete(schema.businesses);
await db.delete(schema.users);
//Broker
-let filePath = `./data/broker.json`
+let filePath = `./data/broker.json`;
let data: string = readFileSync(filePath, 'utf8');
-const userData: User[] = JSON.parse(data); // Erwartet ein Array von Objekten
-const generatedUserData = []
-console.log(userData.length)
+const userData: User[] = JSON.parse(data); // Erwartet ein Array von Objekten
+const generatedUserData = [];
+console.log(userData.length);
+let i = 0,
+ male = 0,
+ female = 0;
+const targetPathProfile = `./pictures/profile`;
+deleteFilesOfDir(targetPathProfile);
+const targetPathLogo = `./pictures/logo`;
+deleteFilesOfDir(targetPathLogo);
for (const user of userData) {
- 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 });
- generatedUserData.push(u[0].insertedId);
+ delete user.id;
+ user.licensedIn = user.licensedIn.map(l => `${l['name']}|${l['value']}`);
+ user.hasCompanyLogo = true;
+ user.hasProfile = true;
+ const u = await db.insert(schema.users).values(user).returning({ insertedId: schema.users.id, gender: schema.users.gender });
+ generatedUserData.push(u[0].insertedId);
+ i++;
+ if (u[0].gender === 'male') {
+ male++;
+ const data = readFileSync(`./pictures/profile_base/Mann_${male}.jpg`);
+ await storeProfilePicture(data, u[0].insertedId);
+ } else {
+ female++;
+ const data = readFileSync(`./pictures/profile_base/Frau_${male}.jpg`);
+ await storeProfilePicture(data, u[0].insertedId);
+ }
+ const data = readFileSync(`./pictures/logos_base/${i}.jpg`);
+ await storeCompanyLogo(data, u[0].insertedId);
}
//Business Listings
-filePath = `./data/businesses.json`
+filePath = `./data/businesses.json`;
data = readFileSync(filePath, 'utf8');
-const businessJsonData = JSON.parse(data) as BusinessListing[]; // Erwartet ein Array von Objekten
+const businessJsonData = JSON.parse(data) as BusinessListing[]; // Erwartet ein Array von Objekten
for (const business of businessJsonData) {
- delete business.id
- business.created = new Date(business.created)
- business.userId = getRandomItem(generatedUserData);
- await db.insert(schema.businesses).values(business);
+ delete business.id;
+ business.created = new Date(business.created);
+ business.userId = getRandomItem(generatedUserData);
+ await db.insert(schema.businesses).values(business);
}
//Corporate Listings
-filePath = `./data/commercials.json`
+filePath = `./data/commercials.json`;
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) {
- const id = commercial.id;
- delete commercial.id
- commercial.imageOrder=['1.jpg'];
- commercial.imagePath=id
- commercial.created = getRandomDateWithinLastYear();
- commercial.userId = getRandomItem(generatedUserData);
- await db.insert(schema.commercials).values(commercial);
+ const id = commercial.id;
+ delete commercial.id;
+
+ commercial.imageOrder = getFilenames(id);
+ commercial.imagePath = id;
+ commercial.created = getRandomDateWithinLastYear();
+ commercial.userId = getRandomItem(generatedUserData);
+ await db.insert(schema.commercials).values(commercial);
}
//End
-await client.end()
+await client.end();
function getRandomItem(arr: T[]): T {
- if (arr.length === 0) {
- throw new Error('The array is empty.');
- }
+ if (arr.length === 0) {
+ throw new Error('The array is empty.');
+ }
- const randomIndex = Math.floor(Math.random() * arr.length);
- return arr[randomIndex];
+ const randomIndex = Math.floor(Math.random() * arr.length);
+ return arr[randomIndex];
+}
+function getFilenames(id: string): string[] {
+ try {
+ let filePath = `./pictures/property/${id}`;
+ return readdirSync(filePath);
+ } catch (e) {
+ return null;
+ }
}
function getRandomDateWithinLastYear(): Date {
- const currentDate = new Date();
- const lastYear = new Date(currentDate.getFullYear() - 1, currentDate.getMonth(), currentDate.getDate());
-
- const timeDiff = currentDate.getTime() - lastYear.getTime();
- const randomTimeDiff = Math.random() * timeDiff;
- const randomDate = new Date(lastYear.getTime() + randomTimeDiff);
-
- return randomDate;
- }
\ No newline at end of file
+ const currentDate = new Date();
+ const lastYear = new Date(currentDate.getFullYear() - 1, currentDate.getMonth(), currentDate.getDate());
+
+ const timeDiff = currentDate.getTime() - lastYear.getTime();
+ const randomTimeDiff = Math.random() * timeDiff;
+ const randomDate = new Date(lastYear.getTime() + randomTimeDiff);
+
+ return randomDate;
+}
+async function storeProfilePicture(buffer: Buffer, userId: string) {
+ let quality = 50;
+ const output = await sharp(buffer)
+ .resize({ width: 300 })
+ .avif({ quality }) // Verwende AVIF
+ //.webp({ quality }) // Verwende Webp
+ .toBuffer();
+ await sharp(output).toFile(`./pictures/profile/${userId}.avif`);
+}
+
+async function storeCompanyLogo(buffer: Buffer, userId: string) {
+ let quality = 50;
+ const output = await sharp(buffer)
+ .resize({ width: 300 })
+ .avif({ quality }) // Verwende AVIF
+ //.webp({ quality }) // Verwende Webp
+ .toBuffer();
+ await sharp(output).toFile(`./pictures/logo/${userId}.avif`); // Ersetze Dateierweiterung
+ // await fs.outputFile(`./pictures/logo/${userId}`, file.buffer);
+}
+
+function deleteFilesOfDir(directoryPath) {
+ // Überprüfen, ob das Verzeichnis existiert
+ if (existsSync(directoryPath)) {
+ // Den Inhalt des Verzeichnisses synchron löschen
+ try {
+ readdirSync(directoryPath).forEach(file => {
+ const filePath = join(directoryPath, file);
+ // Wenn es sich um ein Verzeichnis handelt, rekursiv löschen
+ if (statSync(filePath).isDirectory()) {
+ rimraf.sync(filePath);
+ } else {
+ // Wenn es sich um eine Datei handelt, direkt löschen
+ unlinkSync(filePath);
+ }
+ });
+ console.log('Der Inhalt des Verzeichnisses wurde erfolgreich gelöscht.');
+ } catch (err) {
+ console.error('Fehler beim Löschen des Verzeichnisses:', err);
+ }
+ } else {
+ console.log('Das Verzeichnis existiert nicht.');
+ }
+}
diff --git a/bizmatch-server/src/drizzle/migrations/0001_rapid_daimon_hellstrom.sql b/bizmatch-server/src/drizzle/migrations/0001_rapid_daimon_hellstrom.sql
new file mode 100644
index 0000000..6ccab12
--- /dev/null
+++ b/bizmatch-server/src/drizzle/migrations/0001_rapid_daimon_hellstrom.sql
@@ -0,0 +1 @@
+ALTER TABLE "commercials" ALTER COLUMN "imageOrder" SET DATA TYPE varchar(200)[];
\ No newline at end of file
diff --git a/bizmatch-server/src/drizzle/migrations/0002_black_zaladane.sql b/bizmatch-server/src/drizzle/migrations/0002_black_zaladane.sql
new file mode 100644
index 0000000..eda9b80
--- /dev/null
+++ b/bizmatch-server/src/drizzle/migrations/0002_black_zaladane.sql
@@ -0,0 +1,7 @@
+DO $$ BEGIN
+ CREATE TYPE "gender" AS ENUM('male', 'female');
+EXCEPTION
+ WHEN duplicate_object THEN null;
+END $$;
+--> statement-breakpoint
+ALTER TABLE "users" ADD COLUMN "gender" "gender";
\ No newline at end of file
diff --git a/bizmatch-server/src/drizzle/migrations/meta/0001_snapshot.json b/bizmatch-server/src/drizzle/migrations/meta/0001_snapshot.json
new file mode 100644
index 0000000..61a17bb
--- /dev/null
+++ b/bizmatch-server/src/drizzle/migrations/meta/0001_snapshot.json
@@ -0,0 +1,460 @@
+{
+ "id": "3e4b8c5f-4474-4877-abec-38283408ee34",
+ "prevId": "f6d421f9-2394-4a1c-9268-9e46285f0a41",
+ "version": "5",
+ "dialect": "pg",
+ "tables": {
+ "businesses": {
+ "name": "businesses",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "userId": {
+ "name": "userId",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "type": {
+ "name": "type",
+ "type": "integer",
+ "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
+ },
+ "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
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "businesses_userId_users_id_fk": {
+ "name": "businesses_userId_users_id_fk",
+ "tableFrom": "businesses",
+ "tableTo": "users",
+ "columnsFrom": [
+ "userId"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "commercials": {
+ "name": "commercials",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "userId": {
+ "name": "userId",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "type": {
+ "name": "type",
+ "type": "integer",
+ "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
+ },
+ "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
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "website": {
+ "name": "website",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "phoneNumber": {
+ "name": "phoneNumber",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "imageOrder": {
+ "name": "imageOrder",
+ "type": "varchar(200)[]",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "imagePath": {
+ "name": "imagePath",
+ "type": "varchar(50)",
+ "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
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "commercials_userId_users_id_fk": {
+ "name": "commercials_userId_users_id_fk",
+ "tableFrom": "commercials",
+ "tableTo": "users",
+ "columnsFrom": [
+ "userId"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "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": "varchar(100)[]",
+ "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": "varchar(50)[]",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/bizmatch-server/src/drizzle/migrations/meta/0002_snapshot.json b/bizmatch-server/src/drizzle/migrations/meta/0002_snapshot.json
new file mode 100644
index 0000000..8f4dff0
--- /dev/null
+++ b/bizmatch-server/src/drizzle/migrations/meta/0002_snapshot.json
@@ -0,0 +1,474 @@
+{
+ "id": "ad48c6eb-2d04-442f-9242-b6765553c7c4",
+ "prevId": "3e4b8c5f-4474-4877-abec-38283408ee34",
+ "version": "5",
+ "dialect": "pg",
+ "tables": {
+ "businesses": {
+ "name": "businesses",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "userId": {
+ "name": "userId",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "type": {
+ "name": "type",
+ "type": "integer",
+ "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
+ },
+ "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
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "businesses_userId_users_id_fk": {
+ "name": "businesses_userId_users_id_fk",
+ "tableFrom": "businesses",
+ "tableTo": "users",
+ "columnsFrom": [
+ "userId"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "commercials": {
+ "name": "commercials",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "userId": {
+ "name": "userId",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "type": {
+ "name": "type",
+ "type": "integer",
+ "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
+ },
+ "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
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "website": {
+ "name": "website",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "phoneNumber": {
+ "name": "phoneNumber",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "imageOrder": {
+ "name": "imageOrder",
+ "type": "varchar(200)[]",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "imagePath": {
+ "name": "imagePath",
+ "type": "varchar(50)",
+ "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
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "commercials_userId_users_id_fk": {
+ "name": "commercials_userId_users_id_fk",
+ "tableFrom": "commercials",
+ "tableTo": "users",
+ "columnsFrom": [
+ "userId"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "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": "varchar(100)[]",
+ "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": "varchar(50)[]",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "gender": {
+ "name": "gender",
+ "type": "gender",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ }
+ },
+ "enums": {
+ "gender": {
+ "name": "gender",
+ "values": {
+ "male": "male",
+ "female": "female"
+ }
+ }
+ },
+ "schemas": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/bizmatch-server/src/drizzle/migrations/meta/_journal.json b/bizmatch-server/src/drizzle/migrations/meta/_journal.json
index bddfc24..633985c 100644
--- a/bizmatch-server/src/drizzle/migrations/meta/_journal.json
+++ b/bizmatch-server/src/drizzle/migrations/meta/_journal.json
@@ -8,6 +8,20 @@
"when": 1714913766996,
"tag": "0000_third_spacker_dave",
"breakpoints": true
+ },
+ {
+ "idx": 1,
+ "version": "5",
+ "when": 1714981666488,
+ "tag": "0001_rapid_daimon_hellstrom",
+ "breakpoints": true
+ },
+ {
+ "idx": 2,
+ "version": "5",
+ "when": 1714982539265,
+ "tag": "0002_black_zaladane",
+ "breakpoints": true
}
]
}
\ No newline at end of file
diff --git a/bizmatch-server/src/drizzle/schema.ts b/bizmatch-server/src/drizzle/schema.ts
index 1b496cf..9397274 100644
--- a/bizmatch-server/src/drizzle/schema.ts
+++ b/bizmatch-server/src/drizzle/schema.ts
@@ -1,8 +1,8 @@
-import { integer, serial, text, pgTable, timestamp, jsonb, varchar, char, numeric, boolean, uuid, real, doublePrecision } from 'drizzle-orm/pg-core';
+import { integer, serial, text, pgTable, timestamp, jsonb, varchar, char, numeric, boolean, uuid, real, doublePrecision, pgEnum } from 'drizzle-orm/pg-core';
import { InferInsertModel, InferModel, InferModelFromColumns, InferSelectModel, relations, sql } from 'drizzle-orm';
export const PG_CONNECTION = 'PG_CONNECTION';
-
+export const genderEnum = pgEnum('gender', ['male','female']);
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
firstname: varchar('firstname', { length: 255 }).notNull(),
@@ -19,6 +19,7 @@ export const users = pgTable('users', {
hasProfile: boolean('hasProfile'),
hasCompanyLogo: boolean('hasCompanyLogo'),
licensedIn:varchar('licensedIn', { length: 50 }).array(),
+ gender: genderEnum('gender'),
});
export const businesses = pgTable('businesses', {
@@ -68,7 +69,7 @@ export const commercials = pgTable('commercials', {
email: varchar('email', { length: 255 }),
website: varchar('website', { length: 255 }),
phoneNumber: varchar('phoneNumber', { length: 255 }),
- imageOrder:varchar('imageOrder',{length:30}).array(),
+ imageOrder:varchar('imageOrder',{length:200}).array(),
imagePath:varchar('imagePath',{length:50}),
created: timestamp('created'),
updated: timestamp('updated'),
diff --git a/bizmatch-server/src/image/image.controller.ts b/bizmatch-server/src/image/image.controller.ts
index a27c544..b31c547 100644
--- a/bizmatch-server/src/image/image.controller.ts
+++ b/bizmatch-server/src/image/image.controller.ts
@@ -1,76 +1,74 @@
-import { Body, Controller, Delete, Get, Inject, Param, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
+import { Controller, Delete, Get, Inject, Param, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
+import { FileInterceptor } from '@nestjs/platform-express';
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
import { Logger } from 'winston';
-import { FileInterceptor } from '@nestjs/platform-express';
import { FileService } from '../file/file.service.js';
-import { SelectOptionsService } from '../select-options/select-options.service.js';
import { ListingsService } from '../listings/listings.service.js';
+import { SelectOptionsService } from '../select-options/select-options.service.js';
-import { Entity, EntityData } from 'redis-om';
-import { businesses, commercials } from 'src/drizzle/schema.js';
+import { commercials } from 'src/drizzle/schema.js';
import { CommercialPropertyListing } from 'src/models/db.model.js';
@Controller('image')
export class ImageController {
-
- constructor(private fileService:FileService,
- private listingService:ListingsService,
- @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
- private selectOptions:SelectOptionsService) {
- }
-
- @Post('uploadPropertyPicture/:id')
- @UseInterceptors(FileInterceptor('file'),)
- async uploadPropertyPicture(@UploadedFile() file: Express.Multer.File,@Param('id') id:string) {
- const imagename = await this.fileService.storePropertyPicture(file,id);
- // await this.listingService.addImage(id,imagename);
- }
+ constructor(
+ private fileService: FileService,
+ private listingService: ListingsService,
+ @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
+ private selectOptions: SelectOptionsService,
+ ) {}
- @Post('uploadProfile/:id')
- @UseInterceptors(FileInterceptor('file'),)
- async uploadProfile(@UploadedFile() file: Express.Multer.File,@Param('id') id:string) {
- await this.fileService.storeProfilePicture(file,id);
- }
-
- @Post('uploadCompanyLogo/:id')
- @UseInterceptors(FileInterceptor('file'),)
- async uploadCompanyLogo(@UploadedFile() file: Express.Multer.File,@Param('id') id:string) {
- await this.fileService.storeCompanyLogo(file,id);
- }
-
- @Get(':id')
- async getPropertyImagesById(@Param('id') id:string): Promise {
- const result = await this.listingService.findById(id,commercials);
- const listing = result as CommercialPropertyListing;
- if (listing.imageOrder){
- return listing.imageOrder
- } else {
- const imageOrder = await this.fileService.getPropertyImages(id);
- listing.imageOrder=imageOrder;
- this.listingService.updateListing(listing.id,listing,commercials);
- return imageOrder;
- }
- }
- @Get('profileImages/:userids')
- async getProfileImagesForUsers(@Param('userids') userids:string): Promise {
- return await this.fileService.getProfileImagesForUsers(userids);
- }
- @Get('companyLogos/:userids')
- async getCompanyLogosForUsers(@Param('userids') userids:string): Promise {
- return await this.fileService.getCompanyLogosForUsers(userids);
- }
-
- @Delete('propertyPicture/:listingid/:imagename')
- async deletePropertyImagesById(@Param('listingid') listingid:string,@Param('imagename') imagename:string): Promise {
- this.fileService.deleteImage(`pictures/property/${listingid}/${imagename}`);
- // await this.listingService.deleteImage(listingid,imagename);
- }
- @Delete('logo/:userid/')
- async deleteLogoImagesById(@Param('id') id:string): Promise {
- this.fileService.deleteImage(`pictures/property//${id}`)
- }
- @Delete('profile/:userid/')
- async deleteProfileImagesById(@Param('id') id:string): Promise {
- this.fileService.deleteImage(`pictures/property//${id}`)
+ @Post('uploadPropertyPicture/:id')
+ @UseInterceptors(FileInterceptor('file'))
+ async uploadPropertyPicture(@UploadedFile() file: Express.Multer.File, @Param('id') id: string) {
+ const imagename = await this.fileService.storePropertyPicture(file, id);
+ await this.listingService.addImage(id, imagename);
+ }
+
+ @Post('uploadProfile/:id')
+ @UseInterceptors(FileInterceptor('file'))
+ async uploadProfile(@UploadedFile() file: Express.Multer.File, @Param('id') id: string) {
+ await this.fileService.storeProfilePicture(file, id);
+ }
+
+ @Post('uploadCompanyLogo/:id')
+ @UseInterceptors(FileInterceptor('file'))
+ async uploadCompanyLogo(@UploadedFile() file: Express.Multer.File, @Param('id') id: string) {
+ await this.fileService.storeCompanyLogo(file, id);
+ }
+
+ @Get(':id')
+ async getPropertyImagesById(@Param('id') id: string): Promise {
+ const result = await this.listingService.findById(id, commercials);
+ const listing = result as CommercialPropertyListing;
+ if (listing.imageOrder) {
+ return listing.imageOrder;
+ } else {
+ const imageOrder = await this.fileService.getPropertyImages(id);
+ listing.imageOrder = imageOrder;
+ this.listingService.updateListing(listing.id, listing, commercials);
+ return imageOrder;
}
+ }
+ @Get('profileImages/:userids')
+ async getProfileImagesForUsers(@Param('userids') userids: string): Promise {
+ return await this.fileService.getProfileImagesForUsers(userids);
+ }
+ @Get('companyLogos/:userids')
+ async getCompanyLogosForUsers(@Param('userids') userids: string): Promise {
+ return await this.fileService.getCompanyLogosForUsers(userids);
+ }
+
+ @Delete('propertyPicture/:listingid/:imagename')
+ async deletePropertyImagesById(@Param('listingid') listingid: string, @Param('imagename') imagename: string): Promise {
+ this.fileService.deleteImage(`pictures/property/${listingid}/${imagename}`);
+ }
+ @Delete('logo/:userid/')
+ async deleteLogoImagesById(@Param('id') id: string): Promise {
+ this.fileService.deleteImage(`pictures/property//${id}`);
+ }
+ @Delete('profile/:userid/')
+ async deleteProfileImagesById(@Param('id') id: string): Promise {
+ this.fileService.deleteImage(`pictures/property//${id}`);
+ }
}
diff --git a/bizmatch-server/src/listings/business-listings.controller.ts b/bizmatch-server/src/listings/business-listings.controller.ts
index 0858dac..0b087a0 100644
--- a/bizmatch-server/src/listings/business-listings.controller.ts
+++ b/bizmatch-server/src/listings/business-listings.controller.ts
@@ -1,50 +1,47 @@
import { Body, Controller, Delete, Get, Inject, Param, Post, Put } from '@nestjs/common';
-import { FileService } from '../file/file.service.js';
-import { convertStringToNullUndefined } from '../utils.js';
-import { ListingsService } from './listings.service.js';
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
import { Logger } from 'winston';
-import { ListingCriteria } from '../models/main.model.js';
import { businesses } from '../drizzle/schema.js';
+import { ListingCriteria } from '../models/main.model.js';
+import { ListingsService } from './listings.service.js';
@Controller('listings/business')
export class BusinessListingsController {
-
- constructor(private readonly listingsService:ListingsService,
- @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) {
- }
+ constructor(
+ private readonly listingsService: ListingsService,
+ @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
+ ) {}
@Get(':id')
- findById(@Param('id') id:string): any {
- return this.listingsService.findById(id,businesses);
+ findById(@Param('id') id: string): any {
+ return this.listingsService.findById(id, businesses);
}
@Get('user/:userid')
- findByUserId(@Param('userid') userid:string): any {
- return this.listingsService.findByUserId(userid,businesses);
+ findByUserId(@Param('userid') userid: string): any {
+ return this.listingsService.findByUserId(userid, businesses);
}
@Post('search')
find(@Body() criteria: ListingCriteria): any {
- return this.listingsService.findListingsByCriteria(criteria,businesses);
+ return this.listingsService.findListingsByCriteria(criteria, businesses);
}
@Post()
- create(@Body() listing: any){
+ create(@Body() listing: any) {
this.logger.info(`Save Listing`);
- this.listingsService.createListing(listing,businesses)
+ return this.listingsService.createListing(listing, businesses);
}
@Put()
- update(@Body() listing: any){
+ update(@Body() listing: any) {
this.logger.info(`Save Listing`);
- this.listingsService.updateListing(listing.id,listing,businesses)
+ return this.listingsService.updateListing(listing.id, listing, businesses);
}
@Delete(':id')
- deleteById(@Param('id') id:string){
- this.listingsService.deleteListing(id,businesses)
+ deleteById(@Param('id') id: string) {
+ this.listingsService.deleteListing(id, businesses);
}
@Get('states/all')
getStates(): any {
return this.listingsService.getStates(businesses);
}
}
-
diff --git a/bizmatch-server/src/listings/listings.service.ts b/bizmatch-server/src/listings/listings.service.ts
index 19c2a06..a3a8034 100644
--- a/bizmatch-server/src/listings/listings.service.ts
+++ b/bizmatch-server/src/listings/listings.service.ts
@@ -1,29 +1,20 @@
import { Inject, Injectable } from '@nestjs/common';
-import {
- ListingCriteria,
- ListingType,
- ImageProperty,
- ListingCategory,
- ResponseBusinessListing
-} from '../models/main.model.js';
-import { convertStringToNullUndefined } from '../utils.js';
-import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
-import { Logger } from 'winston';
-import { EntityData, EntityId, Schema, SchemaDefinition } from 'redis-om';
-import { SQL, eq, gte, ilike, lte, sql, and} from 'drizzle-orm';
-import { PG_CONNECTION, businesses, commercials, } from '../drizzle/schema.js';
+import { and, eq, gte, ilike, lte, sql } from 'drizzle-orm';
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
-import * as schema from '../drizzle/schema.js';
-import { PgTableFn, PgTableWithColumns, QueryBuilder } from 'drizzle-orm/pg-core';
+import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
import { BusinessListing, CommercialPropertyListing } from 'src/models/db.model.js';
+import { Logger } from 'winston';
+import * as schema from '../drizzle/schema.js';
+import { PG_CONNECTION, businesses, commercials } from '../drizzle/schema.js';
+import { ListingCriteria } from '../models/main.model.js';
@Injectable()
export class ListingsService {
-
- constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
- @Inject(PG_CONNECTION) private conn: NodePgDatabase,) {
- }
- private getConditions(criteria: ListingCriteria,table: typeof businesses | typeof commercials): any[] {
+ constructor(
+ @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
+ @Inject(PG_CONNECTION) private conn: NodePgDatabase,
+ ) {}
+ private getConditions(criteria: ListingCriteria, table: typeof businesses | typeof commercials): any[] {
const conditions = [];
if (criteria.type) {
conditions.push(eq(table.type, criteria.type));
@@ -51,36 +42,49 @@ export class ListingsService {
async findListingsByCriteria(criteria: ListingCriteria, table: typeof businesses | typeof commercials): Promise<{ data: Record[]; total: number }> {
const start = criteria.start ? criteria.start : 0;
const length = criteria.length ? criteria.length : 12;
- return await this.findListings(table, criteria, start, length)
+ return await this.findListings(table, criteria, start, length);
}
private async findListings(table: typeof businesses | typeof commercials, criteria: ListingCriteria, start = 0, length = 12): Promise {
- const conditions = this.getConditions(criteria,table)
+ const conditions = this.getConditions(criteria, table);
const [data, total] = await Promise.all([
- this.conn.select().from(table).where(and(...conditions)).offset(start).limit(length),
- this.conn.select({ count: sql`count(*)` }).from(table).where(and(...conditions)).then((result) => Number(result[0].count)),
+ this.conn
+ .select()
+ .from(table)
+ .where(and(...conditions))
+ .offset(start)
+ .limit(length),
+ this.conn
+ .select({ count: sql`count(*)` })
+ .from(table)
+ .where(and(...conditions))
+ .then(result => Number(result[0].count)),
]);
return { total, data };
}
async findById(id: string, table: typeof businesses | typeof commercials): Promise {
- const result = await this.conn.select().from(table).where(sql`${table.id} = ${id}`)
- return result[0] as BusinessListing | CommercialPropertyListing
+ const result = await this.conn
+ .select()
+ .from(table)
+ .where(sql`${table.id} = ${id}`);
+ return result[0] as BusinessListing | CommercialPropertyListing;
}
async findByUserId(userId: string, table: typeof businesses | typeof commercials): Promise {
- return await this.conn.select().from(table).where(eq(table.userId, userId)) as BusinessListing[] | CommercialPropertyListing[]
+ return (await this.conn.select().from(table).where(eq(table.userId, userId))) as BusinessListing[] | CommercialPropertyListing[];
}
async createListing(data: BusinessListing | CommercialPropertyListing, table: typeof businesses | typeof commercials): Promise {
- data.created=new Date()
- data.updated=new Date()
- data.visits=0;
- data.lastVisit=null
+ data.created = new Date();
+ data.updated = new Date();
+ data.visits = 0;
+ data.lastVisit = null;
const [createdListing] = await this.conn.insert(table).values(data).returning();
return createdListing as BusinessListing | CommercialPropertyListing;
}
async updateListing(id: string, data: BusinessListing | CommercialPropertyListing, table: typeof businesses | typeof commercials): Promise {
- data.updated=new Date();
+ data.updated = new Date();
+ data.created = new Date(data.created);
const [updateListing] = await this.conn.update(table).set(data).where(eq(table.id, id)).returning();
return updateListing as BusinessListing | CommercialPropertyListing;
}
@@ -89,29 +93,33 @@ export class ListingsService {
await this.conn.delete(table).where(eq(table.id, id));
}
async getStates(table: typeof businesses | typeof commercials): Promise {
- return await this.conn.select({state: table.state,count: sql`count(${table.id})`.mapWith(Number)}).from(table).groupBy(sql`${table.state}`).orderBy(sql`count desc`);
+ return await this.conn
+ .select({ state: table.state, count: sql`count(${table.id})`.mapWith(Number) })
+ .from(table)
+ .groupBy(sql`${table.state}`)
+ .orderBy(sql`count desc`);
}
// ##############################################################
// Images for commercial Properties
// ##############################################################
async updateImageOrder(id: string, imageOrder: string[]) {
- const listing = await this.findById(id, commercials) as unknown as CommercialPropertyListing
+ const listing = (await this.findById(id, commercials)) as unknown as CommercialPropertyListing;
listing.imageOrder = imageOrder;
- await this.updateListing(listing.id, listing, commercials)
+ await this.updateListing(listing.id, listing, commercials);
}
- async deleteImage(id: string, name: string,) {
- const listing = await this.findById(id, commercials) as unknown as CommercialPropertyListing
+ async deleteImage(id: string, name: string) {
+ const listing = (await this.findById(id, commercials)) as unknown as CommercialPropertyListing;
const index = listing.imageOrder.findIndex(im => im === name);
if (index > -1) {
listing.imageOrder.splice(index, 1);
- await this.updateListing(listing.id, listing, commercials)
+ await this.updateListing(listing.id, listing, commercials);
}
}
async addImage(id: string, imagename: string) {
- const listing = await this.findById(id, commercials) as unknown as CommercialPropertyListing
+ const listing = (await this.findById(id, commercials)) as unknown as CommercialPropertyListing;
listing.imageOrder.push(imagename);
- await this.updateListing(listing.id, listing, commercials)
+ listing.imagePath = listing.id;
+ await this.updateListing(listing.id, listing, commercials);
}
-
}
diff --git a/bizmatch-server/src/mail/mail.controller.ts b/bizmatch-server/src/mail/mail.controller.ts
index f8ff3a4..1377b13 100644
--- a/bizmatch-server/src/mail/mail.controller.ts
+++ b/bizmatch-server/src/mail/mail.controller.ts
@@ -1,15 +1,13 @@
-import { Body, Controller, Get, Param, Post } from '@nestjs/common';
+import { Body, Controller, Post } from '@nestjs/common';
+import { User } from 'src/models/db.model.js';
+import { MailInfo } from 'src/models/main.model.js';
import { MailService } from './mail.service.js';
-import { KeycloakUser, MailInfo } from 'src/models/main.model.js';
-
@Controller('mail')
export class MailController {
- constructor(private mailService:MailService){
-
- }
- @Post()
- sendEMail(@Body() mailInfo: MailInfo): Promise< KeycloakUser> {
- return this.mailService.sendInquiry(mailInfo);
- }
+ constructor(private mailService: MailService) {}
+ @Post()
+ sendEMail(@Body() mailInfo: MailInfo): Promise {
+ return this.mailService.sendInquiry(mailInfo);
+ }
}
diff --git a/bizmatch-server/src/mail/mail.module.ts b/bizmatch-server/src/mail/mail.module.ts
index bda9800..f424531 100644
--- a/bizmatch-server/src/mail/mail.module.ts
+++ b/bizmatch-server/src/mail/mail.module.ts
@@ -1,22 +1,27 @@
-import { Module } from '@nestjs/common';
-import { MailService } from './mail.service.js';
-import { MailController } from './mail.controller.js';
import { MailerModule } from '@nestjs-modules/mailer';
-import path, { join } from 'path';
import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter.js';
+import { Module } from '@nestjs/common';
+import path, { join } from 'path';
import { fileURLToPath } from 'url';
-import { AuthModule } from '../auth/auth.module.js';
+import { DrizzleModule } from '../drizzle/drizzle.module.js';
+import { FileService } from '../file/file.service.js';
+import { UserModule } from '../user/user.module.js';
+import { UserService } from '../user/user.service.js';
+import { MailController } from './mail.controller.js';
+import { MailService } from './mail.service.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
@Module({
- imports: [AuthModule,
+ imports: [
+ DrizzleModule,
+ UserModule,
MailerModule.forRoot({
// transport: 'smtps://user@example.com:topsecret@smtp.example.com',
// or
transport: {
host: 'email-smtp.us-east-2.amazonaws.com',
secure: false,
- port:587,
+ port: 587,
// auth: {
// user: 'andreas.knuth@gmail.com',
// pass: 'ksnh xjae dqbv xana',
@@ -38,7 +43,7 @@ const __dirname = path.dirname(__filename);
},
}),
],
- providers: [MailService],
- controllers: [MailController]
+ providers: [MailService, UserService, FileService],
+ controllers: [MailController],
})
export class MailModule {}
diff --git a/bizmatch-server/src/mail/mail.service.ts b/bizmatch-server/src/mail/mail.service.ts
index 756c32f..712aaca 100644
--- a/bizmatch-server/src/mail/mail.service.ts
+++ b/bizmatch-server/src/mail/mail.service.ts
@@ -1,26 +1,41 @@
import { MailerService } from '@nestjs-modules/mailer';
import { Injectable } from '@nestjs/common';
-import { AuthService } from '../auth/auth.service.js';
-import { KeycloakUser, MailInfo } from '../models/main.model.js';
+import path, { join } from 'path';
+import { fileURLToPath } from 'url';
+import { User } from '../models/db.model.js';
+import { MailInfo } from '../models/main.model.js';
+import { UserService } from '../user/user.service.js';
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
@Injectable()
export class MailService {
- constructor(private mailerService: MailerService, private authService:AuthService) {}
-
- async sendInquiry(mailInfo: MailInfo):Promise {
- const user = await this.authService.getUser(mailInfo.userId) as KeycloakUser;
- console.log(JSON.stringify(user));
- await this.mailerService.sendMail({
- to: user.email,
- from: '"Bizmatch Team" ', // override default from
- subject: `Inquiry from ${mailInfo.sender.name}`,
- template: './inquiry', // `.hbs` extension is appended automatically
- context: { // ✏️ filling curly brackets with content
- name: user.firstName,
- inquiry:mailInfo.sender.comments
- },
- });
- return user
- }
-
+ constructor(
+ private mailerService: MailerService,
+ private userService: UserService,
+ ) {}
+
+ async sendInquiry(mailInfo: MailInfo): Promise {
+ //const user = await this.authService.getUser(mailInfo.userId) as KeycloakUser;
+ const user = await this.userService.getUserByMail(mailInfo.email);
+ console.log(JSON.stringify(user));
+ await this.mailerService.sendMail({
+ to: user.email,
+ from: '"Bizmatch Team" ', // override default from
+ subject: `Inquiry from ${mailInfo.sender.name}`,
+ //template: './inquiry', // `.hbs` extension is appended automatically
+ template: join(__dirname, '../..', 'mail/templates/inquiry.hbs'),
+ context: {
+ // ✏️ filling curly brackets with content
+ name: user.firstname,
+ inquiry: mailInfo.sender.comments,
+ internalListingNumber: mailInfo.listing.internalListingNumber,
+ title: mailInfo.listing.title,
+ iname: mailInfo.sender.name,
+ phone: mailInfo.sender.phoneNumber,
+ email: mailInfo.sender.email,
+ },
+ });
+ return user;
}
+}
diff --git a/bizmatch-server/src/models/db.model.ts b/bizmatch-server/src/models/db.model.ts
index fdfc006..13b94b9 100644
--- a/bizmatch-server/src/models/db.model.ts
+++ b/bizmatch-server/src/models/db.model.ts
@@ -1,5 +1,5 @@
export interface User {
- id: string;
+ id?: string;
firstname: string;
lastname: string;
email: string;
diff --git a/bizmatch-server/src/models/main.model.ts b/bizmatch-server/src/models/main.model.ts
index 53c7802..45ce934 100644
--- a/bizmatch-server/src/models/main.model.ts
+++ b/bizmatch-server/src/models/main.model.ts
@@ -65,6 +65,7 @@ export interface ListingCriteria {
realEstateChecked: boolean;
title: string;
category: 'professional|broker';
+ name: string;
}
export interface KeycloakUser {
@@ -148,6 +149,8 @@ export interface AutoCompleteCompleteEvent {
export interface MailInfo {
sender: Sender;
userId: string;
+ email: string;
+ listing?: BusinessListing;
}
export interface Sender {
name?: string;
diff --git a/bizmatch-server/src/select-options/select-options.service.ts b/bizmatch-server/src/select-options/select-options.service.ts
index c11f924..c74d2e7 100644
--- a/bizmatch-server/src/select-options/select-options.service.ts
+++ b/bizmatch-server/src/select-options/select-options.service.ts
@@ -3,113 +3,105 @@ import { ImageType, KeyValue, KeyValueStyle } from '../models/main.model.js';
@Injectable()
export class SelectOptionsService {
-
- constructor() { }
- public typesOfBusiness: Array = [
- { name: 'Automotive', value: '1', icon:'fa-solid fa-car',bgColorClass:'bg-green-100',textColorClass:'text-green-600' },
- { name: 'Industrial Services', value: '2', icon:'fa-solid fa-industry',bgColorClass:'bg-yellow-100',textColorClass:'text-yellow-600'},
- { name: 'Real Estate', value: '3' , icon:'pi pi-building',bgColorClass:'bg-blue-100',textColorClass:'text-blue-600'},
- { name: 'Uncategorized', value: '4' , icon:'pi pi-question',bgColorClass:'bg-cyan-100',textColorClass:'text-cyan-600'},
- { name: 'Retail', value: '5' , icon:'fa-solid fa-money-bill-wave',bgColorClass:'bg-pink-100',textColorClass:'text-pink-600'},
- { name: 'Oilfield SVE and MFG.', value: '6' , icon:'fa-solid fa-oil-well',bgColorClass:'bg-indigo-100',textColorClass:'text-indigo-600'},
- { name: 'Service', value: '7' , icon:'fa-solid fa-umbrella',bgColorClass:'bg-teal-100',textColorClass:'text-teal-600'},
- { name: 'Advertising', value: '8' , icon:'fa-solid fa-rectangle-ad',bgColorClass:'bg-orange-100',textColorClass:'text-orange-600'},
- { name: 'Agriculture', value: '9' , icon:'fa-solid fa-wheat-awn',bgColorClass:'bg-bluegray-100',textColorClass:'text-bluegray-600'},
- { name: 'Franchise', value: '10' , icon:'pi pi-star',bgColorClass:'bg-purple-100',textColorClass:'text-purple-600'},
- { name: 'Professional', value: '11' , icon:'fa-solid fa-user-gear',bgColorClass:'bg-gray-100',textColorClass:'text-gray-600'},
- { name: 'Manufacturing', value: '12' , icon:'fa-solid fa-industry',bgColorClass:'bg-red-100',textColorClass:'text-red-600'},
- { name: 'Food and Restaurant', value: '13' , icon:'fa-solid fa-utensils',bgColorClass:'bg-primary-100',textColorClass:'text-primary-600'},
- ];
- public typesOfCommercialProperty: Array = [
- { name: 'Retail', value: '100' , icon:'fa-solid fa-money-bill-wave',bgColorClass:'bg-pink-100',textColorClass:'text-pink-600'},
- { name: 'Land', value: '101' , icon:'pi pi-building',bgColorClass:'bg-blue-100',textColorClass:'text-blue-600'},
- { name: 'Industrial', value: '102', icon:'fa-solid fa-industry',bgColorClass:'bg-yellow-100',textColorClass:'text-yellow-600'},
- { name: 'Office', value: '103' , icon:'fa-solid fa-umbrella',bgColorClass:'bg-teal-100',textColorClass:'text-teal-600'},
- { name: 'Mixed Use', value: '104' , icon:'fa-solid fa-rectangle-ad',bgColorClass:'bg-orange-100',textColorClass:'text-orange-600'},
- { name: 'Multifamily', value: '105' , icon:'pi pi-star',bgColorClass:'bg-purple-100',textColorClass:'text-purple-600'},
- { name: 'Uncategorized', value: '106' , icon:'pi pi-question',bgColorClass:'bg-cyan-100',textColorClass:'text-cyan-600'},
- ];
- public prices: Array = [
- { name: '$100K', value: '100000' },
- { name: '$250K', value: '250000' },
- { name: '$500K', value: '500000' },
- { name: '$1M', value: '1000000' },
- { name: '$5M', value: '5000000' },
- ];
- public listingCategories: Array = [
- { name: 'Business', value: 'business' },
- { name: 'Commercial Property', value: 'commercialProperty' },
- ]
- public categories: Array = [
- { name: 'Broker', value: 'broker', icon:'pi-image',bgColorClass:'bg-green-100',textColorClass:'text-green-600' },
- { name: 'Professional', value: 'professional', icon:'pi-globe',bgColorClass:'bg-yellow-100',textColorClass:'text-yellow-600' },
- ]
- public imageTypes:ImageType[] = [
- {name:'propertyPicture',upload:'uploadPropertyPicture',delete:'propertyPicture'},
- {name:'companyLogo',upload:'uploadCompanyLogo',delete:'logo'},
- {name:'profile',upload:'uploadProfile',delete:'profile'},
- ]
- private usStates = [
- { name: 'ALABAMA', abbreviation: 'AL'},
- { name: 'ALASKA', abbreviation: 'AK'},
- { name: 'AMERICAN SAMOA', abbreviation: 'AS'},
- { name: 'ARIZONA', abbreviation: 'AZ'},
- { name: 'ARKANSAS', abbreviation: 'AR'},
- { name: 'CALIFORNIA', abbreviation: 'CA'},
- { name: 'COLORADO', abbreviation: 'CO'},
- { name: 'CONNECTICUT', abbreviation: 'CT'},
- { name: 'DELAWARE', abbreviation: 'DE'},
- { name: 'DISTRICT OF COLUMBIA', abbreviation: 'DC'},
- { name: 'FEDERATED STATES OF MICRONESIA', abbreviation: 'FM'},
- { name: 'FLORIDA', abbreviation: 'FL'},
- { name: 'GEORGIA', abbreviation: 'GA'},
- { name: 'GUAM', abbreviation: 'GU'},
- { name: 'HAWAII', abbreviation: 'HI'},
- { name: 'IDAHO', abbreviation: 'ID'},
- { name: 'ILLINOIS', abbreviation: 'IL'},
- { name: 'INDIANA', abbreviation: 'IN'},
- { name: 'IOWA', abbreviation: 'IA'},
- { name: 'KANSAS', abbreviation: 'KS'},
- { name: 'KENTUCKY', abbreviation: 'KY'},
- { name: 'LOUISIANA', abbreviation: 'LA'},
- { name: 'MAINE', abbreviation: 'ME'},
- { name: 'MARSHALL ISLANDS', abbreviation: 'MH'},
- { name: 'MARYLAND', abbreviation: 'MD'},
- { name: 'MASSACHUSETTS', abbreviation: 'MA'},
- { name: 'MICHIGAN', abbreviation: 'MI'},
- { name: 'MINNESOTA', abbreviation: 'MN'},
- { name: 'MISSISSIPPI', abbreviation: 'MS'},
- { name: 'MISSOURI', abbreviation: 'MO'},
- { name: 'MONTANA', abbreviation: 'MT'},
- { name: 'NEBRASKA', abbreviation: 'NE'},
- { name: 'NEVADA', abbreviation: 'NV'},
- { name: 'NEW HAMPSHIRE', abbreviation: 'NH'},
- { name: 'NEW JERSEY', abbreviation: 'NJ'},
- { name: 'NEW MEXICO', abbreviation: 'NM'},
- { name: 'NEW YORK', abbreviation: 'NY'},
- { name: 'NORTH CAROLINA', abbreviation: 'NC'},
- { name: 'NORTH DAKOTA', abbreviation: 'ND'},
- { name: 'NORTHERN MARIANA ISLANDS', abbreviation: 'MP'},
- { name: 'OHIO', abbreviation: 'OH'},
- { name: 'OKLAHOMA', abbreviation: 'OK'},
- { name: 'OREGON', abbreviation: 'OR'},
- { name: 'PALAU', abbreviation: 'PW'},
- { name: 'PENNSYLVANIA', abbreviation: 'PA'},
- { name: 'PUERTO RICO', abbreviation: 'PR'},
- { name: 'RHODE ISLAND', abbreviation: 'RI'},
- { name: 'SOUTH CAROLINA', abbreviation: 'SC'},
- { name: 'SOUTH DAKOTA', abbreviation: 'SD'},
- { name: 'TENNESSEE', abbreviation: 'TN'},
- { name: 'TEXAS', abbreviation: 'TX'},
- { name: 'UTAH', abbreviation: 'UT'},
- { name: 'VERMONT', abbreviation: 'VT'},
- { name: 'VIRGIN ISLANDS', abbreviation: 'VI'},
- { name: 'VIRGINIA', abbreviation: 'VA'},
- { name: 'WASHINGTON', abbreviation: 'WA'},
- { name: 'WEST VIRGINIA', abbreviation: 'WV'},
- { name: 'WISCONSIN', abbreviation: 'WI'},
- { name: 'WYOMING', abbreviation: 'WY' }
- ]
- public locations:Array = [...this.usStates.map(state=>({name:state.name, value:state.abbreviation}))].concat({name:'CANADA',value:"CA"});
-
+ constructor() {}
+ public typesOfBusiness: Array = [
+ { name: 'Automotive', value: '1', icon: 'fa-solid fa-car', bgColorClass: 'bg-green-100', textColorClass: 'text-green-600' },
+ { name: 'Industrial Services', value: '2', icon: 'fa-solid fa-industry', bgColorClass: 'bg-yellow-100', textColorClass: 'text-yellow-600' },
+ { name: 'Real Estate', value: '3', icon: 'pi pi-building', bgColorClass: 'bg-blue-100', textColorClass: 'text-blue-600' },
+ { name: 'Uncategorized', value: '4', icon: 'pi pi-question', bgColorClass: 'bg-cyan-100', textColorClass: 'text-cyan-600' },
+ { name: 'Retail', value: '5', icon: 'fa-solid fa-money-bill-wave', bgColorClass: 'bg-pink-100', textColorClass: 'text-pink-600' },
+ { name: 'Oilfield SVE and MFG.', value: '6', icon: 'fa-solid fa-oil-well', bgColorClass: 'bg-indigo-100', textColorClass: 'text-indigo-600' },
+ { name: 'Service', value: '7', icon: 'fa-solid fa-umbrella', bgColorClass: 'bg-teal-100', textColorClass: 'text-teal-600' },
+ { name: 'Advertising', value: '8', icon: 'fa-solid fa-rectangle-ad', bgColorClass: 'bg-orange-100', textColorClass: 'text-orange-600' },
+ { name: 'Agriculture', value: '9', icon: 'fa-solid fa-wheat-awn', bgColorClass: 'bg-bluegray-100', textColorClass: 'text-bluegray-600' },
+ { name: 'Franchise', value: '10', icon: 'pi pi-star', bgColorClass: 'bg-purple-100', textColorClass: 'text-purple-600' },
+ { name: 'Professional', value: '11', icon: 'fa-solid fa-user-gear', bgColorClass: 'bg-gray-100', textColorClass: 'text-gray-600' },
+ { name: 'Manufacturing', value: '12', icon: 'fa-solid fa-industry', bgColorClass: 'bg-red-100', textColorClass: 'text-red-600' },
+ { name: 'Food and Restaurant', value: '13', icon: 'fa-solid fa-utensils', bgColorClass: 'bg-primary-100', textColorClass: 'text-primary-600' },
+ ];
+ public typesOfCommercialProperty: Array = [
+ { name: 'Retail', value: '100', icon: 'fa-solid fa-money-bill-wave', bgColorClass: 'bg-pink-100', textColorClass: 'text-pink-600' },
+ { name: 'Land', value: '101', icon: 'pi pi-building', bgColorClass: 'bg-blue-100', textColorClass: 'text-blue-600' },
+ { name: 'Industrial', value: '102', icon: 'fa-solid fa-industry', bgColorClass: 'bg-yellow-100', textColorClass: 'text-yellow-600' },
+ { name: 'Office', value: '103', icon: 'fa-solid fa-umbrella', bgColorClass: 'bg-teal-100', textColorClass: 'text-teal-600' },
+ { name: 'Mixed Use', value: '104', icon: 'fa-solid fa-rectangle-ad', bgColorClass: 'bg-orange-100', textColorClass: 'text-orange-600' },
+ { name: 'Multifamily', value: '105', icon: 'pi pi-star', bgColorClass: 'bg-purple-100', textColorClass: 'text-purple-600' },
+ { name: 'Uncategorized', value: '106', icon: 'pi pi-question', bgColorClass: 'bg-cyan-100', textColorClass: 'text-cyan-600' },
+ ];
+ public prices: Array = [
+ { name: '$100K', value: '100000' },
+ { name: '$250K', value: '250000' },
+ { name: '$500K', value: '500000' },
+ { name: '$1M', value: '1000000' },
+ { name: '$5M', value: '5000000' },
+ ];
+ public listingCategories: Array = [
+ { name: 'Business', value: 'business' },
+ { name: 'Commercial Property', value: 'commercialProperty' },
+ ];
+ public categories: Array = [
+ { name: 'Broker', value: 'broker', icon: 'pi-image', bgColorClass: 'bg-green-100', textColorClass: 'text-green-600' },
+ { name: 'Professional', value: 'professional', icon: 'pi-globe', bgColorClass: 'bg-yellow-100', textColorClass: 'text-yellow-600' },
+ ];
+ public imageTypes: ImageType[] = [
+ { name: 'propertyPicture', upload: 'uploadPropertyPicture', delete: 'propertyPicture' },
+ { name: 'companyLogo', upload: 'uploadCompanyLogo', delete: 'logo' },
+ { name: 'profile', upload: 'uploadProfile', delete: 'profile' },
+ ];
+ private usStates = [
+ { name: 'ALABAMA', abbreviation: 'AL' },
+ { name: 'ALASKA', abbreviation: 'AK' },
+ { name: 'ARIZONA', abbreviation: 'AZ' },
+ { name: 'ARKANSAS', abbreviation: 'AR' },
+ { name: 'CALIFORNIA', abbreviation: 'CA' },
+ { name: 'COLORADO', abbreviation: 'CO' },
+ { name: 'CONNECTICUT', abbreviation: 'CT' },
+ { name: 'DELAWARE', abbreviation: 'DE' },
+ { name: 'DISTRICT OF COLUMBIA', abbreviation: 'DC' },
+ { name: 'FLORIDA', abbreviation: 'FL' },
+ { name: 'GEORGIA', abbreviation: 'GA' },
+ { name: 'GUAM', abbreviation: 'GU' },
+ { name: 'HAWAII', abbreviation: 'HI' },
+ { name: 'IDAHO', abbreviation: 'ID' },
+ { name: 'ILLINOIS', abbreviation: 'IL' },
+ { name: 'INDIANA', abbreviation: 'IN' },
+ { name: 'IOWA', abbreviation: 'IA' },
+ { name: 'KANSAS', abbreviation: 'KS' },
+ { name: 'KENTUCKY', abbreviation: 'KY' },
+ { name: 'LOUISIANA', abbreviation: 'LA' },
+ { name: 'MAINE', abbreviation: 'ME' },
+ { name: 'MARYLAND', abbreviation: 'MD' },
+ { name: 'MASSACHUSETTS', abbreviation: 'MA' },
+ { name: 'MICHIGAN', abbreviation: 'MI' },
+ { name: 'MINNESOTA', abbreviation: 'MN' },
+ { name: 'MISSISSIPPI', abbreviation: 'MS' },
+ { name: 'MISSOURI', abbreviation: 'MO' },
+ { name: 'MONTANA', abbreviation: 'MT' },
+ { name: 'NEBRASKA', abbreviation: 'NE' },
+ { name: 'NEVADA', abbreviation: 'NV' },
+ { name: 'NEW HAMPSHIRE', abbreviation: 'NH' },
+ { name: 'NEW JERSEY', abbreviation: 'NJ' },
+ { name: 'NEW MEXICO', abbreviation: 'NM' },
+ { name: 'NEW YORK', abbreviation: 'NY' },
+ { name: 'NORTH CAROLINA', abbreviation: 'NC' },
+ { name: 'NORTH DAKOTA', abbreviation: 'ND' },
+ { name: 'OHIO', abbreviation: 'OH' },
+ { name: 'OKLAHOMA', abbreviation: 'OK' },
+ { name: 'OREGON', abbreviation: 'OR' },
+ { name: 'PALAU', abbreviation: 'PW' },
+ { name: 'PENNSYLVANIA', abbreviation: 'PA' },
+ { name: 'RHODE ISLAND', abbreviation: 'RI' },
+ { name: 'SOUTH CAROLINA', abbreviation: 'SC' },
+ { name: 'SOUTH DAKOTA', abbreviation: 'SD' },
+ { name: 'TENNESSEE', abbreviation: 'TN' },
+ { name: 'TEXAS', abbreviation: 'TX' },
+ { name: 'UTAH', abbreviation: 'UT' },
+ { name: 'VERMONT', abbreviation: 'VT' },
+ { name: 'VIRGINIA', abbreviation: 'VA' },
+ { name: 'WASHINGTON', abbreviation: 'WA' },
+ { name: 'WEST VIRGINIA', abbreviation: 'WV' },
+ { name: 'WISCONSIN', abbreviation: 'WI' },
+ { name: 'WYOMING', abbreviation: 'WY' },
+ ];
+ public locations: Array = [...this.usStates.map(state => ({ name: state.name, value: state.abbreviation }))].concat({ name: 'CANADA', value: 'CA' });
}
diff --git a/bizmatch-server/src/user/user.service.ts b/bizmatch-server/src/user/user.service.ts
index 275f53c..4142932 100644
--- a/bizmatch-server/src/user/user.service.ts
+++ b/bizmatch-server/src/user/user.service.ts
@@ -1,61 +1,77 @@
-import { Get, Inject, Injectable, Param } from '@nestjs/common';
-import { createClient } from 'redis';
-import { Entity, Repository, Schema } from 'redis-om';
-import { ListingCriteria } from '../models/main.model.js';
-import { REDIS_CLIENT } from '../redis/redis.module.js';
-import { FileService } from '../file/file.service.js';
-import { User } from 'src/models/db.model.js';
-import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
-import { Logger } from 'winston';
-import { PG_CONNECTION } from 'src/drizzle/schema.js';
+import { Inject, Injectable } from '@nestjs/common';
+import { and, eq, ilike, or, sql } from 'drizzle-orm';
import { NodePgDatabase } from 'drizzle-orm/node-postgres/driver.js';
+import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
+import { PG_CONNECTION } from 'src/drizzle/schema.js';
+import { User } from 'src/models/db.model.js';
+import { Logger } from 'winston';
import * as schema from '../drizzle/schema.js';
-import { eq, sql,and } from 'drizzle-orm';
+import { FileService } from '../file/file.service.js';
+import { ListingCriteria } from '../models/main.model.js';
@Injectable()
export class UserService {
- constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
- @Inject(PG_CONNECTION) private conn: NodePgDatabase,private fileService:FileService) {
+ constructor(
+ @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
+ @Inject(PG_CONNECTION) private conn: NodePgDatabase,
+ private fileService: FileService,
+ ) {}
+ private getConditions(criteria: ListingCriteria): any[] {
+ const conditions = [];
+ if (criteria.state) {
+ conditions.push(sql`EXISTS (SELECT 1 FROM unnest(users."areasServed") AS area WHERE area LIKE '%' || ${criteria.state} || '%')`);
}
- private getConditions(criteria: ListingCriteria): any[] {
- const conditions = [];
- if (criteria.state) {
- conditions.push(sql`EXISTS (SELECT 1 FROM unnest(users."areasServed") AS area WHERE area LIKE '%' || ${criteria.state} || '%')`);
- }
- return conditions;
- }
- async getUserByMail( id:string){
- const users = await this.conn.select().from(schema.users).where(sql`email = ${id}`) as User[]
- const user = users[0]
- user.hasCompanyLogo=this.fileService.hasCompanyLogo(id);
- user.hasProfile=this.fileService.hasProfile(id);
- return user;
+ if (criteria.name) {
+ conditions.push(or(ilike(schema.users.firstname, `%${criteria.name}%`), ilike(schema.users.lastname, `%${criteria.name}%`)));
}
- async getUserById( id:string){
- const users = await this.conn.select().from(schema.users).where(sql`id = ${id}`) as User[]
- const user = users[0]
- user.hasCompanyLogo=this.fileService.hasCompanyLogo(id);
- user.hasProfile=this.fileService.hasProfile(id);
- return user;
+ return conditions;
+ }
+ async getUserByMail(email: string) {
+ const users = (await this.conn
+ .select()
+ .from(schema.users)
+ .where(sql`email = ${email}`)) as User[];
+ const user = users[0];
+ user.hasCompanyLogo = this.fileService.hasCompanyLogo(user.id);
+ user.hasProfile = this.fileService.hasProfile(user.id);
+ return user;
+ }
+ async getUserById(id: string) {
+ const users = (await this.conn
+ .select()
+ .from(schema.users)
+ .where(sql`id = ${id}`)) as User[];
+ const user = users[0];
+ user.hasCompanyLogo = this.fileService.hasCompanyLogo(id);
+ user.hasProfile = this.fileService.hasProfile(id);
+ return user;
+ }
+ async saveUser(user: any): Promise {
+ if (user.id) {
+ const [updateUser] = await this.conn.update(schema.users).set(user).where(eq(schema.users.id, user.id)).returning();
+ return updateUser as User;
+ } else {
+ const [newUser] = await this.conn.insert(schema.users).values(user).returning();
+ return newUser as User;
}
- async saveUser(user:any):Promise{
- if (user.id){
- const [updateUser] = await this.conn.update(schema.users).set(user).where(eq(schema.users.id, user.id)).returning();
- return updateUser as User;
- } else {
- const [newUser] = await this.conn.insert(schema.users).values(user).returning();
- return newUser as User;
- }
- }
- async findUser(criteria:ListingCriteria){
- const start = criteria.start ? criteria.start : 0;
- const length = criteria.length ? criteria.length : 12;
- const conditions = this.getConditions(criteria)
- const [data, total] = await Promise.all([
- 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 };
- }
-
-}
\ No newline at end of file
+ }
+ async findUser(criteria: ListingCriteria) {
+ const start = criteria.start ? criteria.start : 0;
+ const length = criteria.length ? criteria.length : 12;
+ const conditions = this.getConditions(criteria);
+ const [data, total] = await Promise.all([
+ 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 };
+ }
+}
diff --git a/bizmatch/proxy.conf.json b/bizmatch/proxy.conf.json
index 85795bc..5280472 100644
--- a/bizmatch/proxy.conf.json
+++ b/bizmatch/proxy.conf.json
@@ -7,5 +7,15 @@
"target": "http://localhost:3000",
"secure": false,
"changeOrigin": true
+ },
+ "/logo": {
+ "target": "http://localhost:3000",
+ "secure": false,
+ "changeOrigin": true
+ },
+ "/profile": {
+ "target": "http://localhost:3000",
+ "secure": false,
+ "changeOrigin": true
}
}
\ No newline at end of file
diff --git a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html
index adfc142..707ccaa 100644
--- a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html
+++ b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html
@@ -12,7 +12,7 @@
-
-
-
-
-
-
@if(listing && user && (user.id===listing?.userId || isAdmin())){
}
diff --git a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts
index 0d20b84..9ee3b87 100644
--- a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts
+++ b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts
@@ -1,3 +1,4 @@
+import { Location } from '@angular/common';
import { Component } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router';
@@ -46,7 +47,6 @@ export class DetailsBusinessListingComponent {
listing: BusinessListing;
criteria: ListingCriteria;
mailinfo: MailInfo;
- propertyImages: string[] = [];
environment = environment;
user: User;
description: SafeHtml;
@@ -59,27 +59,28 @@ export class DetailsBusinessListingComponent {
private mailService: MailService,
private messageService: MessageService,
private sanitizer: DomSanitizer,
+ private location: Location,
) {
this.userService.getUserObservable().subscribe(user => {
this.user = user;
+ this.mailinfo = { sender: {}, userId: '', email: user.email };
});
this.criteria = onChange(getCriteriaStateObject(), getSessionStorageHandler);
- this.mailinfo = { sender: {}, userId: '' };
}
async ngOnInit() {
this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, 'business'));
- this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id);
this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description);
}
back() {
- this.router.navigate(['businessListings']);
+ this.location.back();
}
isAdmin() {
return this.userService.hasAdminRole();
}
async mail() {
this.mailinfo.userId = this.listing.userId;
+ this.mailinfo.listing = this.listing;
await this.mailService.mail(this.mailinfo);
this.messageService.add({ severity: 'info', summary: 'Confirmed', detail: 'Your message has been sent to the creator of the listing', life: 3000 });
}
diff --git a/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html
index f2aa1f3..0265946 100644
--- a/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html
+++ b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html
@@ -12,7 +12,7 @@
diff --git a/bizmatch/src/app/pages/listings/business-listings/business-listings.component.scss b/bizmatch/src/app/pages/listings/business-listings/business-listings.component.scss
index 57253e1..3ea0761 100644
--- a/bizmatch/src/app/pages/listings/business-listings/business-listings.component.scss
+++ b/bizmatch/src/app/pages/listings/business-listings/business-listings.component.scss
@@ -1,23 +1,26 @@
#sky-line {
- background-image: url(../../../../assets/images/bw-sky.jpg);
- height: 204px;
- background-position: bottom;
- background-size: cover;
- margin-bottom: -1px;
+ background-image: url(../../../../assets/images/bw-sky.jpg);
+ height: 204px;
+ background-position: bottom;
+ background-size: cover;
+ margin-bottom: -1px;
}
-.search{
- background-color: #343F69;
+.search {
+ background-color: #343f69;
}
::ng-deep p-paginator div {
- background-color: var(--surface-200) !important;
- // background-color: var(--surface-400) !important;
+ background-color: var(--surface-200) !important;
+ // background-color: var(--surface-400) !important;
}
.rounded-image {
- border-radius: 6px;
- // width: 100px;
- max-width: 100px;
- height: 45px;
- border: 1px solid rgba(0,0,0,0.2);
- padding: 1px 1px;
- object-fit: contain;
-}
\ No newline at end of file
+ border-radius: 6px;
+ // width: 100px;
+ max-width: 100px;
+ height: 45px;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ padding: 1px 1px;
+ object-fit: contain;
+}
+::ng-deep span.p-button-label {
+ font-weight: 500;
+}
diff --git a/bizmatch/src/app/pages/listings/business-listings/business-listings.component.ts b/bizmatch/src/app/pages/listings/business-listings/business-listings.component.ts
index f8601c1..c5a003e 100644
--- a/bizmatch/src/app/pages/listings/business-listings/business-listings.component.ts
+++ b/bizmatch/src/app/pages/listings/business-listings/business-listings.component.ts
@@ -6,10 +6,12 @@ import onChange from 'on-change';
import { ButtonModule } from 'primeng/button';
import { CheckboxModule } from 'primeng/checkbox';
import { DropdownModule } from 'primeng/dropdown';
+import { InputGroupModule } from 'primeng/inputgroup';
import { InputTextModule } from 'primeng/inputtext';
import { PaginatorModule } from 'primeng/paginator';
import { StyleClassModule } from 'primeng/styleclass';
import { ToggleButtonModule } from 'primeng/togglebutton';
+import { TooltipModule } from 'primeng/tooltip';
import { BusinessListing } from '../../../../../../bizmatch-server/src/models/db.model';
import { ListingCriteria, ListingType } from '../../../../../../bizmatch-server/src/models/main.model';
import { environment } from '../../../../environments/environment';
@@ -21,7 +23,21 @@ import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler }
@Component({
selector: 'app-business-listings',
standalone: true,
- imports: [CommonModule, StyleClassModule, ButtonModule, CheckboxModule, InputTextModule, DropdownModule, FormsModule, StyleClassModule, ToggleButtonModule, RouterModule, PaginatorModule],
+ imports: [
+ CommonModule,
+ StyleClassModule,
+ ButtonModule,
+ CheckboxModule,
+ InputTextModule,
+ DropdownModule,
+ FormsModule,
+ StyleClassModule,
+ ToggleButtonModule,
+ RouterModule,
+ PaginatorModule,
+ InputGroupModule,
+ TooltipModule,
+ ],
templateUrl: './business-listings.component.html',
styleUrl: './business-listings.component.scss',
})
@@ -36,10 +52,10 @@ export class BusinessListingsComponent {
type: string;
states = [];
state: string;
- first: number = 0;
- rows: number = 12;
totalRecords: number = 0;
ts = new Date().getTime();
+ first: number = 0;
+ rows: number = 12;
public category: 'business' | 'commercialProperty' | 'professionals_brokers' | undefined;
constructor(
@@ -56,7 +72,6 @@ export class BusinessListingsComponent {
this.activatedRoute.params.subscribe(params => {
if (this.activatedRoute.snapshot.fragment === '') {
this.criteria = onChange(createGenericObject
(), getSessionStorageHandler);
- this.first = 0;
}
this.category = (params).type;
this.init();
@@ -68,6 +83,11 @@ export class BusinessListingsComponent {
this.states = statesResult.map(s => s.state).map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
this.search();
}
+ refine() {
+ this.criteria.start = 0;
+ this.criteria.page = 0;
+ this.search();
+ }
async search() {
const listingReponse = await this.listingsService.getListings(this.criteria, 'business');
this.listings = listingReponse.data;
@@ -85,4 +105,7 @@ export class BusinessListingsComponent {
imageErrorHandler(listing: ListingType) {
// listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann
}
+ reset() {
+ this.criteria.title = null;
+ }
}
diff --git a/bizmatch/src/app/pages/listings/commercial-property-listings/commercial-property-listings.component.html b/bizmatch/src/app/pages/listings/commercial-property-listings/commercial-property-listings.component.html
index 6ada800..872eabb 100644
--- a/bizmatch/src/app/pages/listings/commercial-property-listings/commercial-property-listings.component.html
+++ b/bizmatch/src/app/pages/listings/commercial-property-listings/commercial-property-listings.component.html
@@ -5,8 +5,31 @@
-
@@ -19,7 +42,7 @@
- @if (listing.imageOrder.length>0){
+ @if (listing.imageOrder?.length>0){

} @else {
@@ -60,9 +83,12 @@
}
+
+
Total number of Listings: {{ totalRecords }}
+
diff --git a/bizmatch/src/app/pages/listings/commercial-property-listings/commercial-property-listings.component.ts b/bizmatch/src/app/pages/listings/commercial-property-listings/commercial-property-listings.component.ts
index e9860d6..d3dec2c 100644
--- a/bizmatch/src/app/pages/listings/commercial-property-listings/commercial-property-listings.component.ts
+++ b/bizmatch/src/app/pages/listings/commercial-property-listings/commercial-property-listings.component.ts
@@ -6,12 +6,13 @@ import onChange from 'on-change';
import { ButtonModule } from 'primeng/button';
import { CheckboxModule } from 'primeng/checkbox';
import { DropdownModule } from 'primeng/dropdown';
+import { InputGroupModule } from 'primeng/inputgroup';
import { InputTextModule } from 'primeng/inputtext';
import { PaginatorModule } from 'primeng/paginator';
import { StyleClassModule } from 'primeng/styleclass';
import { ToggleButtonModule } from 'primeng/togglebutton';
import { CommercialPropertyListing } from '../../../../../../bizmatch-server/src/models/db.model';
-import { ListingCriteria, ListingType } from '../../../../../../bizmatch-server/src/models/main.model';
+import { ListingCriteria } from '../../../../../../bizmatch-server/src/models/main.model';
import { environment } from '../../../../environments/environment';
import { ImageService } from '../../../services/image.service';
import { ListingsService } from '../../../services/listings.service';
@@ -21,7 +22,7 @@ import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler }
@Component({
selector: 'app-commercial-property-listings',
standalone: true,
- imports: [CommonModule, StyleClassModule, ButtonModule, CheckboxModule, InputTextModule, DropdownModule, FormsModule, StyleClassModule, ToggleButtonModule, RouterModule, PaginatorModule],
+ imports: [CommonModule, StyleClassModule, ButtonModule, CheckboxModule, InputTextModule, DropdownModule, FormsModule, StyleClassModule, ToggleButtonModule, RouterModule, PaginatorModule, InputGroupModule],
templateUrl: './commercial-property-listings.component.html',
styleUrl: './commercial-property-listings.component.scss',
})
@@ -31,15 +32,14 @@ export class CommercialPropertyListingsComponent {
filteredListings: Array;
criteria: ListingCriteria;
realEstateChecked: boolean;
-
+ first: number = 0;
+ rows: number = 12;
maxPrice: string;
minPrice: string;
type: string;
states = [];
statesSet = new Set();
state: string;
- first: number = 0;
- rows: number = 12;
totalRecords: number = 0;
ts = new Date().getTime();
@@ -52,12 +52,12 @@ export class CommercialPropertyListingsComponent {
private imageService: ImageService,
) {
this.criteria = onChange(getCriteriaStateObject(), getSessionStorageHandler);
+ this.criteria.type = undefined;
this.router.getCurrentNavigation();
this.activatedRoute.snapshot;
this.activatedRoute.params.subscribe(params => {
if (this.activatedRoute.snapshot.fragment === '') {
this.criteria = onChange(createGenericObject(), getSessionStorageHandler);
- this.first = 0;
}
this.init();
});
@@ -68,7 +68,11 @@ export class CommercialPropertyListingsComponent {
this.states = statesResult.map(s => s.state).map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
this.search();
}
-
+ refine() {
+ this.criteria.start = 0;
+ this.criteria.page = 0;
+ this.search();
+ }
async search() {
const listingReponse = await this.listingsService.getListings(this.criteria, 'commercialProperty');
this.listings = listingReponse.data;
@@ -83,7 +87,7 @@ export class CommercialPropertyListingsComponent {
this.criteria.pageCount = event.pageCount;
this.search();
}
- imageErrorHandler(listing: ListingType) {
- // listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann
+ reset() {
+ this.criteria.title = null;
}
}
diff --git a/bizmatch/src/app/pages/subscription/account/account.component.html b/bizmatch/src/app/pages/subscription/account/account.component.html
index 0ab3818..1886205 100644
--- a/bizmatch/src/app/pages/subscription/account/account.component.html
+++ b/bizmatch/src/app/pages/subscription/account/account.component.html
@@ -103,6 +103,7 @@
(is shown in every offer)
@if(user?.hasCompanyLogo){
+
} @else {
}
@@ -121,7 +122,7 @@
Your Profile Picture
- @if(user.hasProfile){
+ @if(user?.hasProfile){

} @else {

diff --git a/bizmatch/src/app/pages/subscription/account/account.component.ts b/bizmatch/src/app/pages/subscription/account/account.component.ts
index f7fa798..f74b8f7 100644
--- a/bizmatch/src/app/pages/subscription/account/account.component.ts
+++ b/bizmatch/src/app/pages/subscription/account/account.component.ts
@@ -57,17 +57,25 @@ export class AccountComponent {
public dialogService: DialogService,
) {}
async ngOnInit() {
- const email = this.userService.getUser().email;
- this.user = await this.userService.getByMail(email);
- this.userLicensedIn = this.user.licensedIn.map(l => {
- return { name: l.split('|')[0], value: l.split('|')[1] };
- });
+ const keycloakUser = this.userService.getKeycloakUser();
+ const email = keycloakUser.email;
+ try {
+ this.user = await this.userService.getByMail(email);
+ } catch (e) {
+ this.user = { email, firstname: keycloakUser.firstname, lastname: keycloakUser.lastname };
+ this.user = await this.userService.save(this.user);
+ }
+ this.userLicensedIn = this.user.licensedIn
+ ? this.user.licensedIn.map(l => {
+ return { name: l.split('|')[0], value: l.split('|')[1] };
+ })
+ : [];
this.userSubscriptions = await lastValueFrom(this.subscriptionService.getAllSubscriptions());
if (!this.user.licensedIn || this.user.licensedIn?.length === 0) {
this.user.licensedIn = [''];
}
- this.profileUrl = this.user.hasProfile ? `${environment.apiBaseUrl}/profile/${this.user.id}.avif` : `/assets/images/placeholder.png`;
- this.companyLogoUrl = this.user.hasCompanyLogo ? `${environment.apiBaseUrl}/logo/${this.user.id}.avif` : `/assets/images/placeholder.png`;
+ this.profileUrl = this.user.hasProfile ? `profile/${this.user.id}.avif` : `/assets/images/placeholder.png`;
+ this.companyLogoUrl = this.user.hasCompanyLogo ? `logo/${this.user.id}.avif` : `/assets/images/placeholder.png`;
}
printInvoice(invoice: Invoice) {}
diff --git a/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.html b/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.html
index 44121c1..8e86c8f 100644
--- a/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.html
+++ b/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.html
@@ -36,16 +36,7 @@
diff --git a/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.ts b/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.ts
index 7b0a055..7550ff3 100644
--- a/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.ts
+++ b/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.ts
@@ -85,6 +85,7 @@ export class EditBusinessListingComponent {
draggedImage: ImageProperty;
faTrash = faTrash;
data: CommercialPropertyListing;
+ typesOfBusiness = [];
constructor(
public selectOptions: SelectOptionsService,
private router: Router,
@@ -109,10 +110,13 @@ export class EditBusinessListingComponent {
this.data = this.router.getCurrentNavigation().extras.state['data'];
}
});
+ this.typesOfBusiness = selectOptions.typesOfBusiness.map(e => {
+ return { name: e.name, value: parseInt(e.value) };
+ });
}
async ngOnInit() {
if (this.mode === 'edit') {
- this.listing = await lastValueFrom(this.listingsService.getListingById(this.id));
+ this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, 'business'));
} else {
this.listing = createGenericObject
();
this.listing.listingsCategory = 'business';
diff --git a/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.html b/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.html
index 77d6a74..73a28e1 100644
--- a/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.html
+++ b/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.html
@@ -38,7 +38,7 @@
diff --git a/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.ts b/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.ts
index f100ba4..b5c16d3 100644
--- a/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.ts
+++ b/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.ts
@@ -89,6 +89,7 @@ export class EditCommercialPropertyListingComponent {
suggestions: string[] | undefined;
data: BusinessListing;
userId: string;
+ typesOfCommercialProperty = [];
constructor(
public selectOptions: SelectOptionsService,
private router: Router,
@@ -103,7 +104,6 @@ export class EditCommercialPropertyListingComponent {
private confirmationService: ConfirmationService,
private route: ActivatedRoute,
) {
- // this.user = this.userService.getUser();
// Abonniere Router-Events, um den aktiven Link zu ermitteln
this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
@@ -115,10 +115,13 @@ export class EditCommercialPropertyListingComponent {
this.data = this.router.getCurrentNavigation().extras.state['data'];
}
});
+ this.typesOfCommercialProperty = selectOptions.typesOfCommercialProperty.map(e => {
+ return { name: e.name, value: parseInt(e.value) };
+ });
}
async ngOnInit() {
if (this.mode === 'edit') {
- this.listing = await lastValueFrom(this.listingsService.getListingById(this.id));
+ this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, 'commercialProperty'));
} else {
this.listing = createGenericObject
();
this.listing.userId = await this.userService.getId();
diff --git a/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.html b/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.html
deleted file mode 100644
index a063a02..0000000
--- a/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.html
+++ /dev/null
@@ -1,216 +0,0 @@
-
diff --git a/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.scss b/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.scss
deleted file mode 100644
index 88018d9..0000000
--- a/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.scss
+++ /dev/null
@@ -1,57 +0,0 @@
-.translate-y-5 {
- transform: translateY(5px);
-}
-
-.image-container {
- display: flex; /* Erlaubt ein flexibles Box-Layout */
- flex-wrap: wrap; /* Erlaubt das Umfließen der Elemente auf die nächste Zeile */
- justify-content: flex-start; /* Startet die Anordnung der Elemente am Anfang des Containers */
- align-items: flex-start; /* Ausrichtung der Elemente am Anfang der Querachse */
- padding: 10px; /* Abstand zwischen den Inhalten des Containers und dessen Rand */
- }
-
-.image-container span {
- flex-flow: row;
- display: flex;
- width: fit-content;
- height: fit-content;
-}
-
-.image-container span img {
- max-height: 150px; /* Maximale Höhe der Bilder */
- width: auto; /* Die Breite der Bilder passt sich automatisch an die Höhe an */
- cursor: pointer;
- margin: 10px;
-}
-// .image-container fa-icon {
-// top: 0; /* Positioniert das Icon am oberen Rand des Bildes */
-// right: 0; /* Positioniert das Icon am rechten Rand des Bildes */
-// color: #fff; /* Weiße Farbe für das Icon */
-// background-color: rgba(0,0,0,0.5); /* Halbtransparenter Hintergrund für bessere Sichtbarkeit */
-// padding: 5px; /* Ein wenig Platz um das Icon */
-// cursor: pointer; /* Verwandelt den Cursor in eine Hand, um Interaktivität anzudeuten */
-// }
-
- .image-wrap {
- position: relative; /* Ermöglicht die absolute Positionierung des Icons bezogen auf diesen Container */
- display: inline-block; /* Erlaubt die Inline-Anordnung, falls mehrere Bilder vorhanden sind */
- }
-
- /* Stil für das Bild */
- .image-wrap img {
- max-height: 150px;
- width: auto;
- display: block; /* Verhindert unerwünschten Abstand unter dem Bild */
- }
-
- /* Stil für das FontAwesome Icon */
- .image-wrap fa-icon {
- position: absolute;
- top: 15px; /* Positioniert das Icon am oberen Rand des Bildes */
- right: 15px; /* Positioniert das Icon am rechten Rand des Bildes */
- color: #fff; /* Weiße Farbe für das Icon */
- background-color: rgba(0,0,0,0.5); /* Halbtransparenter Hintergrund für bessere Sichtbarkeit */
- padding: 5px; /* Ein wenig Platz um das Icon */
- cursor: pointer; /* Verwandelt den Cursor in eine Hand, um Interaktivität anzudeuten */
- border-radius: 8px; /* Optional: Abrunden der linken unteren Ecke für ästhetische Zwecke */
- }
\ No newline at end of file
diff --git a/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.ts b/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.ts
deleted file mode 100644
index e9a73e6..0000000
--- a/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.ts
+++ /dev/null
@@ -1,203 +0,0 @@
-import { Component, ViewChild } from '@angular/core';
-import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
-import { lastValueFrom } from 'rxjs';
-import { ListingsService } from '../../../services/listings.service';
-import { SelectOptionsService } from '../../../services/select-options.service';
-import { createGenericObject } from '../../../utils/utils';
-
-import { DragDropModule, moveItemInArray } from '@angular/cdk/drag-drop';
-import { HttpEventType } from '@angular/common/http';
-import { faTrash } from '@fortawesome/free-solid-svg-icons';
-import { AngularCropperjsModule } from 'angular-cropperjs';
-import { MixedCdkDragDropModule } from 'angular-mixed-cdk-drag-drop';
-import { ConfirmationService, MessageService } from 'primeng/api';
-import { CarouselModule } from 'primeng/carousel';
-import { ConfirmDialogModule } from 'primeng/confirmdialog';
-import { DialogModule } from 'primeng/dialog';
-import { DialogService, DynamicDialogModule, DynamicDialogRef } from 'primeng/dynamicdialog';
-import { EditorModule } from 'primeng/editor';
-import { FileUpload, FileUploadModule } from 'primeng/fileupload';
-import { v4 as uuidv4 } from 'uuid';
-import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
-import { AutoCompleteCompleteEvent, ImageProperty, ListingType } from '../../../../../../bizmatch-server/src/models/main.model';
-import { environment } from '../../../../environments/environment';
-import { ImageCropperComponent } from '../../../components/image-cropper/image-cropper.component';
-import { InputNumberModule } from '../../../components/inputnumber/inputnumber.component';
-import { ArrayToStringPipe } from '../../../pipes/array-to-string.pipe';
-import { GeoService } from '../../../services/geo.service';
-import { ImageService } from '../../../services/image.service';
-import { LoadingService } from '../../../services/loading.service';
-import { UserService } from '../../../services/user.service';
-import { SharedModule } from '../../../shared/shared/shared.module';
-import { TOOLBAR_OPTIONS } from '../../utils/defaults';
-@Component({
- selector: 'create-listing',
- standalone: true,
- imports: [
- SharedModule,
- ArrayToStringPipe,
- InputNumberModule,
- CarouselModule,
- DialogModule,
- AngularCropperjsModule,
- FileUploadModule,
- EditorModule,
- DynamicDialogModule,
- DragDropModule,
- ConfirmDialogModule,
- MixedCdkDragDropModule,
- ],
- providers: [MessageService, DialogService, ConfirmationService],
- templateUrl: './edit-listing.component.html',
- styleUrl: './edit-listing.component.scss',
-})
-export class EditListingComponent {
- @ViewChild(FileUpload) public fileUpload: FileUpload;
- listingCategory: 'Business' | 'Commercial Property';
- category: string;
- location: string;
- mode: 'edit' | 'create';
- separator: '\n\n';
- listing: ListingType;
- private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined;
- user: User;
- maxFileSize = 3000000;
- uploadUrl: string;
- environment = environment;
- propertyImages: ImageProperty[];
- responsiveOptions = [
- {
- breakpoint: '1199px',
- numVisible: 1,
- numScroll: 1,
- },
- {
- breakpoint: '991px',
- numVisible: 2,
- numScroll: 1,
- },
- {
- breakpoint: '767px',
- numVisible: 1,
- numScroll: 1,
- },
- ];
- config = { aspectRatio: 16 / 9 };
- editorModules = TOOLBAR_OPTIONS;
- dialogRef: DynamicDialogRef | undefined;
- draggedImage: ImageProperty;
- faTrash = faTrash;
- constructor(
- public selectOptions: SelectOptionsService,
- private router: Router,
- private activatedRoute: ActivatedRoute,
- private listingsService: ListingsService,
- public userService: UserService,
- private messageService: MessageService,
- private geoService: GeoService,
- private imageService: ImageService,
- private loadingService: LoadingService,
- public dialogService: DialogService,
- private confirmationService: ConfirmationService,
- ) {
- this.user = this.userService.getUser();
- // Abonniere Router-Events, um den aktiven Link zu ermitteln
- this.router.events.subscribe(event => {
- if (event instanceof NavigationEnd) {
- this.mode = event.url === '/createListing' ? 'create' : 'edit';
- }
- });
- }
- async ngOnInit() {
- if (this.mode === 'edit') {
- this.listing = await lastValueFrom(this.listingsService.getListingById(this.id));
- } else {
- const uuid = sessionStorage.getItem('uuid') ? sessionStorage.getItem('uuid') : uuidv4();
- sessionStorage.setItem('uuid', uuid);
- this.listing = createGenericObject();
- this.listing.id = uuid;
- this.listing.userId = this.user.id;
- }
- this.uploadUrl = `${environment.apiBaseUrl}/bizmatch/image/uploadPropertyPicture/${this.listing.id}`;
- this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id);
- }
-
- async save() {
- sessionStorage.removeItem('uuid');
- // await this.listingsService.save(this.listing, this.listing.listingsCategory);
- this.messageService.add({ severity: 'info', summary: 'Confirmed', detail: 'Listing changes have been persisted', life: 3000 });
- }
-
- suggestions: string[] | undefined;
-
- async search(event: AutoCompleteCompleteEvent) {
- const result = await lastValueFrom(this.geoService.findCitiesStartingWith(event.query, this.listing.state));
- this.suggestions = result.map(r => r.city).slice(0, 5);
- }
-
- select(event: any) {
- const imageUrl = URL.createObjectURL(event.files[0]);
- this.dialogRef = this.dialogService.open(ImageCropperComponent, {
- data: {
- imageUrl: imageUrl,
- fileUpload: this.fileUpload,
- ratioVariable: false,
- },
- header: 'Edit Image',
- width: '50vw',
- modal: true,
- closeOnEscape: true,
- keepInViewport: true,
- closable: false,
- breakpoints: {
- '960px': '75vw',
- '640px': '90vw',
- },
- });
- this.dialogRef.onClose.subscribe(cropper => {
- if (cropper) {
- this.loadingService.startLoading('uploadImage');
- cropper.getCroppedCanvas().toBlob(async blob => {
- this.imageService.uploadImage(blob, 'uploadPropertyPicture', this.listing.id).subscribe(
- async event => {
- if (event.type === HttpEventType.Response) {
- console.log('Upload abgeschlossen', event.body);
- this.loadingService.stopLoading('uploadImage');
- this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id);
- }
- },
- error => console.error('Fehler beim Upload:', error),
- );
- }, 'image/jpg');
- cropper.destroy();
- }
- });
- }
-
- deleteConfirm(imageName: string) {
- this.confirmationService.confirm({
- target: event.target as EventTarget,
- message: `Do you want to delete this image ${imageName}?`,
- header: 'Delete Confirmation',
- icon: 'pi pi-info-circle',
- acceptButtonStyleClass: 'p-button-danger p-button-text',
- rejectButtonStyleClass: 'p-button-text p-button-text',
- acceptIcon: 'none',
- rejectIcon: 'none',
-
- accept: async () => {
- await this.imageService.deleteListingImage(this.listing.id, imageName);
- this.messageService.add({ severity: 'info', summary: 'Confirmed', detail: 'Image deleted' });
- this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id);
- },
- reject: () => {
- console.log('deny');
- },
- });
- }
-
- onDrop(event: { previousIndex: number; currentIndex: number }) {
- moveItemInArray(this.propertyImages, event.previousIndex, event.currentIndex);
- this.listingsService.changeImageOrder(this.listing.id, this.propertyImages);
- }
-}
diff --git a/bizmatch/src/app/pages/subscription/favorites/favorites.component.ts b/bizmatch/src/app/pages/subscription/favorites/favorites.component.ts
index e0d3c0e..a7014aa 100644
--- a/bizmatch/src/app/pages/subscription/favorites/favorites.component.ts
+++ b/bizmatch/src/app/pages/subscription/favorites/favorites.component.ts
@@ -1,30 +1,28 @@
import { Component } from '@angular/core';
-import { MenuAccountComponent } from '../../menu-account/menu-account.component';
-import dataListings from '../../../../assets/data/listings.json';
-import { SharedModule } from '../../../shared/shared/shared.module';
-import { UserService } from '../../../services/user.service';
-import { lastValueFrom } from 'rxjs';
-import { ListingsService } from '../../../services/listings.service';
-import { SelectOptionsService } from '../../../services/select-options.service';
import { User } from '../../../../../../bizmatch-server/src/models/db.model';
import { ListingType } from '../../../../../../bizmatch-server/src/models/main.model';
+import { ListingsService } from '../../../services/listings.service';
+import { SelectOptionsService } from '../../../services/select-options.service';
+import { UserService } from '../../../services/user.service';
+import { SharedModule } from '../../../shared/shared/shared.module';
+import { MenuAccountComponent } from '../../menu-account/menu-account.component';
@Component({
selector: 'app-favorites',
standalone: true,
imports: [MenuAccountComponent, SharedModule],
templateUrl: './favorites.component.html',
- styleUrl: './favorites.component.scss'
+ styleUrl: './favorites.component.scss',
})
export class FavoritesComponent {
user: User;
- listings: Array =[]//= dataListings as unknown as Array;
- favorites: Array
- constructor(public userService: UserService, private listingsService:ListingsService, public selectOptions:SelectOptionsService){
- this.user=this.userService.getUser();
+ listings: Array = []; //= dataListings as unknown as Array;
+ favorites: Array;
+ constructor(public userService: UserService, private listingsService: ListingsService, public selectOptions: SelectOptionsService) {
+ this.user = this.userService.getKeycloakUser();
}
- async ngOnInit(){
- // this.listings=await lastValueFrom(this.listingsService.getAllListings());
- this.favorites=this.listings.filter(l=>l.favoritesForUser?.includes(this.user.id));
+ async ngOnInit() {
+ // this.listings=await lastValueFrom(this.listingsService.getAllListings());
+ this.favorites = this.listings.filter(l => l.favoritesForUser?.includes(this.user.id));
}
}
diff --git a/bizmatch/src/app/pages/subscription/my-listing/my-listing.component.ts b/bizmatch/src/app/pages/subscription/my-listing/my-listing.component.ts
index 2adda0c..2fa42d2 100644
--- a/bizmatch/src/app/pages/subscription/my-listing/my-listing.component.ts
+++ b/bizmatch/src/app/pages/subscription/my-listing/my-listing.component.ts
@@ -1,5 +1,6 @@
import { ChangeDetectorRef, Component } from '@angular/core';
import { ConfirmationService, MessageService } from 'primeng/api';
+import { User } from '../../../../../../bizmatch-server/src/models/db.model';
import { ListingType } from '../../../../../../bizmatch-server/src/models/main.model';
import { ListingsService } from '../../../services/listings.service';
import { SelectOptionsService } from '../../../services/select-options.service';
@@ -18,7 +19,7 @@ import { MenuAccountComponent } from '../../menu-account/menu-account.component'
export class MyListingComponent {
listings: Array = []; //dataListings as unknown as Array;
myListings: Array;
- userId: string;
+ user: User;
isBusinessListing = isBusinessListing;
isCommercialPropertyListing = isCommercialPropertyListing;
constructor(
@@ -30,13 +31,15 @@ export class MyListingComponent {
private messageService: MessageService,
) {}
async ngOnInit() {
- this.userId = await this.userService.getId();
- this.myListings = await this.listingsService.getListingByUserId(this.userId);
+ const keycloakUser = this.userService.getKeycloakUser();
+ const email = keycloakUser.email;
+ this.user = await this.userService.getByMail(email);
+ this.myListings = await this.listingsService.getListingByUserId(this.user.id);
}
async deleteListing(listing: ListingType) {
await this.listingsService.deleteListing(listing.id, getListingType(listing));
- this.myListings = await this.listingsService.getListingByUserId(this.userId);
+ this.myListings = await this.listingsService.getListingByUserId(this.user.id);
}
confirm(event: Event, listing: ListingType) {
diff --git a/bizmatch/src/app/services/user.service.ts b/bizmatch/src/app/services/user.service.ts
index d683696..17d9e49 100644
--- a/bizmatch/src/app/services/user.service.ts
+++ b/bizmatch/src/app/services/user.service.ts
@@ -69,7 +69,7 @@ export class UserService {
isLoggedIn(): boolean {
return this.$isLoggedIn();
}
- getUser(): User {
+ getKeycloakUser(): User {
return this.user;
}
getUserObservable(): Observable {
diff --git a/bizmatch/src/app/shared/shared/shared.module.ts b/bizmatch/src/app/shared/shared/shared.module.ts
index cac5dbc..0eb3f9d 100644
--- a/bizmatch/src/app/shared/shared/shared.module.ts
+++ b/bizmatch/src/app/shared/shared/shared.module.ts
@@ -1,35 +1,74 @@
-import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
-import { Component } from '@angular/core';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { RouterModule } from '@angular/router';
+import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
+import { AutoCompleteModule } from 'primeng/autocomplete';
import { ButtonModule } from 'primeng/button';
import { CheckboxModule } from 'primeng/checkbox';
-import { InputTextModule } from 'primeng/inputtext';
-import { StyleClassModule } from 'primeng/styleclass';
-import { DropdownModule } from 'primeng/dropdown';
-import { FormsModule } from '@angular/forms';
-import { ToggleButtonModule } from 'primeng/togglebutton';
-import { TagModule } from 'primeng/tag';
-import { ActivatedRoute, RouterModule } from '@angular/router';
-import { InputTextareaModule } from 'primeng/inputtextarea';
import { ChipModule } from 'primeng/chip';
-import { DividerModule } from 'primeng/divider';
-import { TableModule } from 'primeng/table';
-import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
-import { MenuAccountComponent } from '../../pages/menu-account/menu-account.component';
-import { InputNumberModule } from 'primeng/inputnumber';
import { ConfirmDialogModule } from 'primeng/confirmdialog';
import { ConfirmPopupModule } from 'primeng/confirmpopup';
-import { ToastModule } from 'primeng/toast';
-import { AutoCompleteModule } from 'primeng/autocomplete';
+import { DividerModule } from 'primeng/divider';
+import { DropdownModule } from 'primeng/dropdown';
+import { InputGroupModule } from 'primeng/inputgroup';
+import { InputNumberModule } from 'primeng/inputnumber';
import { InputSwitchModule } from 'primeng/inputswitch';
-
+import { InputTextModule } from 'primeng/inputtext';
+import { InputTextareaModule } from 'primeng/inputtextarea';
+import { StyleClassModule } from 'primeng/styleclass';
+import { TableModule } from 'primeng/table';
+import { TagModule } from 'primeng/tag';
+import { ToastModule } from 'primeng/toast';
+import { MenuAccountComponent } from '../../pages/menu-account/menu-account.component';
@NgModule({
declarations: [],
imports: [
- CommonModule, StyleClassModule, DividerModule,ButtonModule, TableModule, InputTextModule, DropdownModule, FormsModule, ChipModule,InputTextareaModule, RouterModule,FontAwesomeModule,MenuAccountComponent,InputNumberModule,ConfirmDialogModule,ConfirmPopupModule, ToastModule, CheckboxModule, AutoCompleteModule,InputSwitchModule
+ CommonModule,
+ StyleClassModule,
+ DividerModule,
+ ButtonModule,
+ TableModule,
+ InputTextModule,
+ DropdownModule,
+ FormsModule,
+ ChipModule,
+ InputTextareaModule,
+ RouterModule,
+ FontAwesomeModule,
+ MenuAccountComponent,
+ InputNumberModule,
+ ConfirmDialogModule,
+ ConfirmPopupModule,
+ ToastModule,
+ CheckboxModule,
+ AutoCompleteModule,
+ InputSwitchModule,
+ InputGroupModule,
+ ],
+ exports: [
+ CommonModule,
+ StyleClassModule,
+ DividerModule,
+ ButtonModule,
+ TableModule,
+ InputTextModule,
+ DropdownModule,
+ FormsModule,
+ ChipModule,
+ InputTextareaModule,
+ RouterModule,
+ FontAwesomeModule,
+ MenuAccountComponent,
+ InputNumberModule,
+ ConfirmDialogModule,
+ ConfirmPopupModule,
+ ToastModule,
+ CheckboxModule,
+ AutoCompleteModule,
+ TagModule,
+ InputSwitchModule,
+ InputGroupModule,
],
- exports:[
- CommonModule, StyleClassModule, DividerModule,ButtonModule, TableModule, InputTextModule, DropdownModule, FormsModule, ChipModule,InputTextareaModule,RouterModule,FontAwesomeModule,MenuAccountComponent,InputNumberModule,ConfirmDialogModule,ConfirmPopupModule, ToastModule, CheckboxModule, AutoCompleteModule, TagModule,InputSwitchModule
- ]
})
-export class SharedModule { }
+export class SharedModule {}