diff --git a/.env b/.env index 48c2e28..068a238 100644 --- a/.env +++ b/.env @@ -11,7 +11,7 @@ TWILIO_SID= TWILIO_TOKEN= COPYRIGHT=Copyright © 2021 MKD. All rights reserved. POWERED_BY=Powered By MKD.ca -NODE_PORT=3001 +NODE_PORT=3048 GRAPHQL_PORT=9001 EMAIL_SMTP_PROTOCOL=smtp EMAIL_SMTP_SMTP_HOST=smtp.mailtrap.io @@ -62,7 +62,7 @@ DB_PORT=3306 DB_DSN= DB_HOSTNAME=localhost DB_USERNAME=root -DB_PASSWORD= +DB_PASSWORD=ayobamidavid DB_DATABASE=mkd_test_1 DB_DBDRIVER=mysqli DB_DBPREFIX= diff --git a/models/index.js b/models/index.js index 59f86f1..ca33815 100644 --- a/models/index.js +++ b/models/index.js @@ -1,4 +1,4 @@ -'use strict'; +"use strict"; /*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2020*/ /** * Sequelize File @@ -8,44 +8,51 @@ * @author Ryan Wong * */ -const fs = require('fs'); -const path = require('path'); -let Sequelize = require('sequelize'); +const fs = require("fs"); +const path = require("path"); +let Sequelize = require("sequelize"); const basename = path.basename(__filename); -const dotenv = require('dotenv'); +const dotenv = require("dotenv"); dotenv.config(); let db = {}; -let sequelize = new Sequelize(process.env.DB_DATABASE, process.env.DB_USERNAME, process.env.DB_PASSWORD, { - dialect: process.env.DB_ADAPTER, - username: process.env.DB_USERNAME, - password: process.env.DB_PASSWORD, - database: process.env.DB_NAME, - host: process.env.DB_HOSTNAME, - port: process.env.DB_PORT, - logging: console.log, - timezone: '-04:00', - pool: { - maxConnections: 1, - minConnections: 0, - maxIdleTime: 100, - }, - define: { - timestamps: false, - underscoredAll: true, - underscored: true, - }, -}); +let sequelize = new Sequelize( + process.env.DB_DATABASE, + process.env.DB_USERNAME, + process.env.DB_PASSWORD, + { + dialect: process.env.DB_ADAPTER, + username: process.env.DB_USERNAME, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + host: process.env.DB_HOSTNAME, + port: process.env.DB_PORT, + logging: console.log, + timezone: "-04:00", + pool: { + maxConnections: 1, + minConnections: 0, + maxIdleTime: 100, + }, + define: { + timestamps: false, + underscoredAll: true, + underscored: true, + }, + } +); -// sequelize.sync({ force: true }); +sequelize.sync(); fs.readdirSync(__dirname) .filter((file) => { - return file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js'; + return ( + file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js" + ); }) .forEach((file) => { - var model = sequelize['import'](path.join(__dirname, file)); + var model = sequelize["import"](path.join(__dirname, file)); db[model.name] = model; }); diff --git a/package-lock.json b/package-lock.json index dd1d3ba..161c4e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -456,6 +456,17 @@ "node": ">=6" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -1535,6 +1546,26 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, + "node_modules/bootstrap": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.7.tgz", + "integrity": "sha512-7KgiD8UHjfcPBHEpDNg+zGz8L3LqR3GVwqZiBRFX04a1BCArZOz1r2kjly2HQ0WokqTO0v1nF+QAt8dsW4lKlw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peer": true, + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, "node_modules/bootstrap-select": { "version": "1.13.18", "resolved": "https://registry.npmjs.org/bootstrap-select/-/bootstrap-select-1.13.18.tgz", @@ -5723,6 +5754,39 @@ "node": ">=8.10.0" } }, + "node_modules/gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gcp-metadata/node_modules/gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/gcs-resumable-upload": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-2.3.3.tgz", @@ -5967,6 +6031,68 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/google-auth-library": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz", + "integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/google-auth-library/node_modules/gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/google-auth-library/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/google-auth-library/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true, + "peer": true + }, "node_modules/google-gax": { "version": "1.15.3", "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-1.15.3.tgz", @@ -6089,6 +6215,35 @@ "node": ">= 4.5.0" } }, + "node_modules/google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "deprecated": "Package is no longer maintained", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "node-forge": "^1.3.1" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/google-p12-pem/node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "optional": true, + "peer": true, + "engines": { + "node": ">= 6.13.0" + } + }, "node_modules/got": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", @@ -6231,6 +6386,40 @@ "graphql": "0.13.1 - 14" } }, + "node_modules/gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gtoken/node_modules/gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/handlebars": { "version": "4.7.6", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", @@ -7251,6 +7440,13 @@ "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", "integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==" }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "license": "MIT", + "peer": true + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7273,6 +7469,17 @@ "node": ">= 10" } }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "node_modules/json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -8273,11 +8480,23 @@ } }, "node_modules/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, "engines": { "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/node-forge": { @@ -10406,6 +10625,12 @@ "node": ">=6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, "node_modules/trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -10774,6 +10999,12 @@ "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz", "integrity": "sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes=" }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -10795,6 +11026,16 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which-boxed-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz", @@ -11427,6 +11668,12 @@ "protobufjs": "^6.8.6" } }, + "@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "peer": true + }, "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -12355,6 +12602,13 @@ } } }, + "bootstrap": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.7.tgz", + "integrity": "sha512-7KgiD8UHjfcPBHEpDNg+zGz8L3LqR3GVwqZiBRFX04a1BCArZOz1r2kjly2HQ0WokqTO0v1nF+QAt8dsW4lKlw==", + "peer": true, + "requires": {} + }, "bootstrap-select": { "version": "1.13.18", "resolved": "https://registry.npmjs.org/bootstrap-select/-/bootstrap-select-1.13.18.tgz", @@ -16200,6 +16454,33 @@ "node-fetch": "^2.3.0" } }, + "gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "optional": true, + "peer": true, + "requires": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + }, + "dependencies": { + "gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "optional": true, + "peer": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + } + } + } + }, "gcs-resumable-upload": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-2.3.3.tgz", @@ -16397,6 +16678,57 @@ "path-is-absolute": "^1.0.0" } }, + "google-auth-library": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz", + "integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==", + "optional": true, + "peer": true, + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "dependencies": { + "gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "optional": true, + "peer": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true, + "peer": true + } + } + }, "google-gax": { "version": "1.15.3", "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-1.15.3.tgz", @@ -16491,6 +16823,25 @@ } } }, + "google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "optional": true, + "peer": true, + "requires": { + "node-forge": "^1.3.1" + }, + "dependencies": { + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "optional": true, + "peer": true + } + } + }, "got": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", @@ -16599,6 +16950,34 @@ "object-path": "^0.11.4" } }, + "gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "optional": true, + "peer": true, + "requires": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + }, + "dependencies": { + "gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "optional": true, + "peer": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + } + } + } + }, "handlebars": { "version": "4.7.6", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", @@ -17377,6 +17756,12 @@ "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", "integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==" }, + "jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "peer": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -17396,6 +17781,16 @@ "doc-path": "2.3.0" } }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "optional": true, + "peer": true, + "requires": { + "bignumber.js": "^9.0.0" + } + }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -18266,9 +18661,12 @@ "integrity": "sha1-GA6scAPgxwdhjvMTaPYvhLKmkJE=" }, "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } }, "node-forge": { "version": "0.7.6", @@ -19954,6 +20352,11 @@ } } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -20253,6 +20656,11 @@ "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz", "integrity": "sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes=" }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, "websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -20268,6 +20676,15 @@ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which-boxed-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz", diff --git a/public/frontend_css/style.css b/public/frontend_css/style.css index d9a9ac3..71ad9fb 100644 --- a/public/frontend_css/style.css +++ b/public/frontend_css/style.css @@ -16,7 +16,8 @@ body { } @font-face { font-family: "Bradford LL"; - src: url("/fonts/BradfordLL-Regular.woff2") format("woff2"), url("/fonts/BradfordLL-Regular.woff") format("woff"); + src: url("/fonts/BradfordLL-Regular.woff2") format("woff2"), + url("/fonts/BradfordLL-Regular.woff") format("woff"); font-weight: normal; font-style: normal; font-display: swap; @@ -24,21 +25,24 @@ body { @font-face { font-family: "Bradford LL"; - src: url("/fonts/BradfordLL-Italic.woff2") format("woff2"), url("/fonts/BradfordLL-Italic.woff") format("woff"); + src: url("/fonts/BradfordLL-Italic.woff2") format("woff2"), + url("/fonts/BradfordLL-Italic.woff") format("woff"); font-weight: normal; font-style: italic; font-display: swap; } @font-face { font-family: "Necto Mono"; - src: url("/fonts/Necto-Mono.woff2") format("woff2"), url("/fonts/Necto-Mono.woff") format("woff"); + src: url("/fonts/Necto-Mono.woff2") format("woff2"), + url("/fonts/Necto-Mono.woff") format("woff"); font-weight: normal; font-style: normal; font-display: swap; } @font-face { font-family: "TT Nooks Script"; - src: url("/fonts/TTNooksScript-Bold.woff2") format("woff2"), url("/fonts/TTNooksScript-Bold.woff") format("woff"); + src: url("/fonts/TTNooksScript-Bold.woff2") format("woff2"), + url("/fonts/TTNooksScript-Bold.woff") format("woff"); font-weight: bold; font-style: normal; font-display: swap; @@ -843,6 +847,9 @@ input::-ms-input-placeholder { width: -moz-max-content; padding-bottom: 4px; border-bottom: 1px solid black; + position: absolute; + bottom: 4px; + left: 50%; } #page4 .customImgRow img { width: 335px; @@ -1439,3 +1446,64 @@ img.image-missing { display: none; border-left: none; } + +#resetQuizButton, +#resumeButton { + background: #737a73; + color: #fff; + font: 12px "Necto Mono"; + border: none; + border-radius: 4px; + padding: 10px 32px; + margin-left: 8px; + cursor: pointer; + transition: all 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275); + outline: none; +} +#resetQuizButton:hover, +#resumeButton:hover, +#resetQuizButton:focus, +#resumeButton:focus { + background: #444242; + color: #fff; +} + +#questionNavBar .nav-btn { + font: 12px "Necto Mono"; + border-radius: 4px !important; + padding: 10px 16px !important; + margin: 0 4px; + min-width: 32px; + min-height: 32px; + border: none; + font-weight: bold; + cursor: pointer; + transition: background 0.2s, color 0.2s; + text-align: center; + vertical-align: middle; + display: inline-flex; + align-items: center; + justify-content: center; +} +#questionNavBar .nav-btn.answered { + background: #43a047; + color: #fff; + border: 2px solid #388e3c; +} +#questionNavBar .nav-btn.current { + background: #1976d2; + color: #fff; + border: 3px solid #1565c0; + box-shadow: 0 0 8px 2px rgba(25, 118, 210, 0.15); + z-index: 2; +} +#questionNavBar .nav-btn.unanswered { + background: #ccc; + color: #888; + border: 2px solid #bbb; +} +#questionNavBar .nav-btn:hover, +#questionNavBar .nav-btn:focus { + filter: brightness(0.95); + outline: none; +} diff --git a/public/frontend_js/quiz-test.js b/public/frontend_js/quiz-test.js index 929f710..c40d821 100644 --- a/public/frontend_js/quiz-test.js +++ b/public/frontend_js/quiz-test.js @@ -1,7 +1,9 @@ let url_preset = ""; let finalActives = []; -let dataToReturn = localStorage.getItem("answers") ? JSON.parse(localStorage.getItem("answers")) : []; +let dataToReturn = localStorage.getItem("answers") + ? JSON.parse(localStorage.getItem("answers")) + : []; let uniqueQuestionsShowed = []; let lastQuizResponseShown; let lastShowedQuestionId = null; @@ -62,6 +64,7 @@ let nextQuestionTimeoutCounter = 3000; let selectionQuestionTimeoutCounter = 6000; let closeResponseTimeoutCounter = 5000; let timeout; +let responseCountdownInterval; const mainImage = $(".main-image-container img"); fetch(url_preset + "/configurations") @@ -99,7 +102,13 @@ let oldAnswers = []; const customerId = document.getElementById("customer-id"); const customerEmail = document.getElementById("customer-email"); if (customerId || customerEmail) { - fetch(url_preset + "/v1/api/order/customer?id=" + customerId?.innerText + "&email=" + customerEmail?.innerText) + fetch( + url_preset + + "/v1/api/order/customer?id=" + + customerId?.innerText + + "&email=" + + customerEmail?.innerText + ) .then((res) => res.json()) .then((data) => { if (data.success && data.data) { @@ -180,17 +189,31 @@ function showPreparingPage() { } async function showResults() { - const { accumlatedUniqueWeights, sortedWeightsArray } = getUniqueAccumlatedWeights(dataToReturn); + const { accumlatedUniqueWeights, sortedWeightsArray } = + getUniqueAccumlatedWeights(dataToReturn); const accumlatedBLActives = getUniqueBlackListActives(dataToReturn); - const { activesToAdd, activesToRemove } = await getEngineRules(accumlatedUniqueWeights); - const { sortedFinalActiveslist, sortedFinalActiveslistWithScores } = await calculatePrioritySelection(accumlatedUniqueWeights); - const filteredActivesListInitial = filterBlacklistActives(sortedFinalActiveslistWithScores); - finalActives = applyFinalCalculations(filteredActivesListInitial, activesToAdd, activesToRemove, dataToReturn); + const { activesToAdd, activesToRemove } = await getEngineRules( + accumlatedUniqueWeights + ); + const { sortedFinalActiveslist, sortedFinalActiveslistWithScores } = + await calculatePrioritySelection(accumlatedUniqueWeights); + const filteredActivesListInitial = filterBlacklistActives( + sortedFinalActiveslistWithScores + ); + finalActives = applyFinalCalculations( + filteredActivesListInitial, + activesToAdd, + activesToRemove, + dataToReturn + ); console.log("accumlated weights", accumlatedUniqueWeights); console.log("black listed actives", accumlatedBLActives); console.log("full actives list", sortedFinalActiveslist); - console.log("full actives list with scores", sortedFinalActiveslistWithScores); + console.log( + "full actives list with scores", + sortedFinalActiveslistWithScores + ); console.log("after first filter", filteredActivesListInitial); console.log("final actives List", finalActives); @@ -203,7 +226,12 @@ async function showResults() { $("#page7").css("display", "block"); } // showResults function ends here -function applyFinalCalculations(blFilterdActiveList, activesToAdd, activesToRemove, answersArray) { +function applyFinalCalculations( + blFilterdActiveList, + activesToAdd, + activesToRemove, + answersArray +) { //select top 5 //checkup here to see if it is first time or not let finalActivesList = []; @@ -351,7 +379,10 @@ async function getEngineRules(uniqueWeights) { //between let min = rule.min; let max = rule.max; - if (uniqueWeights[ruleOutputVariable] >= min && uniqueWeights[ruleOutputVariable] <= max) { + if ( + uniqueWeights[ruleOutputVariable] >= min && + uniqueWeights[ruleOutputVariable] <= max + ) { if (actionTaken == 1) { //add activesInQuestion.forEach((aiq) => { @@ -384,7 +415,8 @@ function getUniqueAccumlatedWeights(answersArray) { let weightsArray = []; let accumlatedUniqueWeightsWihBase = {}; answersArray.forEach(function (answer) { - if (answer.weights && Object.keys(answer.weights).length) weightsArray.push(answer.weights); + if (answer.weights && Object.keys(answer.weights).length) + weightsArray.push(answer.weights); }); if (weightsArray.length == 0) { return { accumlatedUniqueWeightsWihBase, sortedWeightsArray: [] }; @@ -393,8 +425,12 @@ function getUniqueAccumlatedWeights(answersArray) { Object.keys(weight).forEach(function (key) { if (accumlatedUniqueWeightsWihBase.hasOwnProperty(key)) { accumlatedUniqueWeightsWihBase[key] = { - value: parseFloat(accumlatedUniqueWeightsWihBase[key].value) + parseFloat(weight[key].value), - base: parseFloat(accumlatedUniqueWeightsWihBase[key].base) + parseFloat(weight[key].base), + value: + parseFloat(accumlatedUniqueWeightsWihBase[key].value) + + parseFloat(weight[key].value), + base: + parseFloat(accumlatedUniqueWeightsWihBase[key].base) + + parseFloat(weight[key].base), }; } else { accumlatedUniqueWeightsWihBase[key] = { @@ -406,37 +442,60 @@ function getUniqueAccumlatedWeights(answersArray) { }); let accumlatedUniqueWeights = {}; - Object.entries(accumlatedUniqueWeightsWihBase).forEach(([variableName, { value, base }]) => { - accumlatedUniqueWeights[variableName] = parseFloat(value) / parseFloat(base); - }); - let sortedEntries = Object.entries(accumlatedUniqueWeights).sort(function (a, b) { + Object.entries(accumlatedUniqueWeightsWihBase).forEach( + ([variableName, { value, base }]) => { + accumlatedUniqueWeights[variableName] = + parseFloat(value) / parseFloat(base); + } + ); + let sortedEntries = Object.entries(accumlatedUniqueWeights).sort(function ( + a, + b + ) { return b[1] - a[1]; }); return { accumlatedUniqueWeights, sortedWeightsArray: sortedEntries }; } async function calculatePrioritySelection(accumlatedUniqueWeights) { - const outputVariableList = await getFullOutputVariablesList().then((data) => data.output_variables); + const outputVariableList = await getFullOutputVariablesList().then( + (data) => data.output_variables + ); const activesList = await getFullActivesList().then((data) => data.actives); const finalActiveScores = {}; for (const active of activesList) { //equation const activeName = active.name; - let activesListWeightsScores = active.variables_scores ? JSON.parse(active.variables_scores) : {}; + let activesListWeightsScores = active.variables_scores + ? JSON.parse(active.variables_scores) + : {}; //filter empty active weights score - activesListWeightsScores = Object.entries(activesListWeightsScores).filter(([outputVarName, score]) => { - return score; - }); - let filteredActivesWeightScores = Object.fromEntries(activesListWeightsScores); + activesListWeightsScores = Object.entries(activesListWeightsScores).filter( + ([outputVarName, score]) => { + return score; + } + ); + let filteredActivesWeightScores = Object.fromEntries( + activesListWeightsScores + ); Object.entries(filteredActivesWeightScores).forEach(([name, score]) => { const outputVariableAccumlatedWeight = accumlatedUniqueWeights[name]; if (outputVariableAccumlatedWeight) { - const outputVariablePriority = outputVariableList.find((ovar) => ovar.name == name).priority; + const outputVariablePriority = outputVariableList.find( + (ovar) => ovar.name == name + ).priority; if (finalActiveScores.hasOwnProperty(activeName)) { - finalActiveScores[activeName] = parseFloat(finalActiveScores[activeName]) + parseFloat(outputVariableAccumlatedWeight) * parseFloat(outputVariablePriority / 100) * parseFloat(score); + finalActiveScores[activeName] = + parseFloat(finalActiveScores[activeName]) + + parseFloat(outputVariableAccumlatedWeight) * + parseFloat(outputVariablePriority / 100) * + parseFloat(score); } else { - finalActiveScores[activeName] = parseFloat(outputVariableAccumlatedWeight) * parseFloat(outputVariablePriority / 100) * parseFloat(score); + finalActiveScores[activeName] = + parseFloat(outputVariableAccumlatedWeight) * + parseFloat(outputVariablePriority / 100) * + parseFloat(score); } } }); @@ -448,8 +507,12 @@ async function calculatePrioritySelection(accumlatedUniqueWeights) { finalDividedList[active] = parseFloat(score / 1000); } }); - let sortedFinalActiveslistWithScores = Object.entries(finalDividedList).sort(([, a], [, b]) => b - a); - let sortedFinalActiveslist = Object.keys(finalDividedList).sort((a, b) => finalDividedList[b] - finalDividedList[a]); + let sortedFinalActiveslistWithScores = Object.entries(finalDividedList).sort( + ([, a], [, b]) => b - a + ); + let sortedFinalActiveslist = Object.keys(finalDividedList).sort( + (a, b) => finalDividedList[b] - finalDividedList[a] + ); return { sortedFinalActiveslist, sortedFinalActiveslistWithScores }; } function getUniqueBlackListActives(answersArray) { @@ -479,14 +542,22 @@ async function createProfile(uniqueWeights) {

${sectionTitle}

- ${await makePercentageDivs(uniqueWeights, section.output_variable_list, sectionTitle)} + ${await makePercentageDivs( + uniqueWeights, + section.output_variable_list, + sectionTitle + )}
`; container.append(containerTemplate); } } -async function makePercentageDivs(uniqueWeights, output_variable_list, sectionTitle) { +async function makePercentageDivs( + uniqueWeights, + output_variable_list, + sectionTitle +) { let accumlatedString = ""; for (const item of output_variable_list) { @@ -509,7 +580,10 @@ async function makePercentageDivs(uniqueWeights, output_variable_list, sectionTi `; accumlatedString += tmp; - profile_characteristics[sectionTitle].push({ name: varName, percentage: percentage }); + profile_characteristics[sectionTitle].push({ + name: varName, + percentage: percentage, + }); } return accumlatedString; } @@ -520,7 +594,11 @@ async function getOutputVariableRangesResponses(varName, percentage) { const requiredRange = rangesResponses.find(function (rr) { let minRange = parseFloat(Object.keys(rr)[0].split("-")[0]); let maxRange = parseFloat(Object.keys(rr)[0].split("-")[1]); - if (Math.round(percentage) >= minRange && Math.round(percentage) <= maxRange) return rr; + if ( + Math.round(percentage) >= minRange && + Math.round(percentage) <= maxRange + ) + return rr; }); if (requiredRange) { let currResponse = requiredRange[Object.keys(requiredRange)[0]]; @@ -597,7 +675,11 @@ function getProfileSections() { function getActivesList(outputVariablesNames) { return new Promise(function (res, rej) { $.ajax({ - url: url_preset + `/api/v1/output-variables/actives-list?names_list=${outputVariablesNames.join(",")}`, + url: + url_preset + + `/api/v1/output-variables/actives-list?names_list=${outputVariablesNames.join( + "," + )}`, type: "GET", success: function (response) { return res(response.data); @@ -646,7 +728,10 @@ async function nextQuestion(goBack, goBackFromResponse, fromDependedOn) { clearTimeout(timeout); clearTimeout(closeResponseTimeout); if (goBack) { - let stepBack = uniqueQuestionsShowed.length - 2 < 0 ? 0 : uniqueQuestionsShowed.length - 2; + let stepBack = + uniqueQuestionsShowed.length - 2 < 0 + ? 0 + : uniqueQuestionsShowed.length - 2; let backQuizId = uniqueQuestionsShowed[stepBack].quiz; if (stepBack !== 0) { uniqueQuestionsShowed.pop(); @@ -665,7 +750,11 @@ async function nextQuestion(goBack, goBackFromResponse, fromDependedOn) { } $("#questionRow").css("display", "none"); let dependedOnQuestions = totalQuizQuestions.filter(function (qs) { - return qs.depends_on && parseInt(qs.depends_on.split("|")[0]) == totalQuizQuestions[currentQuestionCounter].id; + return ( + qs.depends_on && + parseInt(qs.depends_on.split("|")[0]) == + totalQuizQuestions[currentQuestionCounter].id + ); }); if (dependedOnQuestions.length > 0) { dependedOnQuestions.forEach((dq) => { @@ -694,7 +783,10 @@ async function nextQuestion(goBack, goBackFromResponse, fromDependedOn) { //first get the answer of previous question and store it. if (currentActiveAnswerType && !isSkipStoreAnswer) { - await storeAnswer(totalQuizQuestions[currentQuestionCounter - 1], currentActiveAnswerType); + await storeAnswer( + totalQuizQuestions[currentQuestionCounter - 1], + currentActiveAnswerType + ); } weights = {}; @@ -736,7 +828,9 @@ async function nextQuestion(goBack, goBackFromResponse, fromDependedOn) { // checking if there is any resp onse in question or answer if (currentQuestionCounter != 0) { - apiQues = totalQuizQuestions.find((ques) => ques.id == lastShowedQuestionId); + apiQues = totalQuizQuestions.find( + (ques) => ques.id == lastShowedQuestionId + ); let lastAnswerObject = dataToReturn.find(function (ansObj) { return ansObj.question.id == apiQues?.id; }); @@ -782,9 +876,9 @@ async function nextQuestion(goBack, goBackFromResponse, fromDependedOn) { if (apiQues.id == 20 && apiQues.type == 7) { if (Array.isArray(lastAnswerObject.answer)) { if (lastAnswerObject.answer.length == 1) { - showResponse(null, "We’ll make sure to leave this one out"); + showResponse(null, "We'll make sure to leave this one out"); } else if (lastAnswerObject.answer.length > 1) { - showResponse(null, "We’ll make sure to leave those out"); + showResponse(null, "We'll make sure to leave those out"); } } } else if (apiQues.type == 1 && apiQues.id == 1) { @@ -796,14 +890,20 @@ async function nextQuestion(goBack, goBackFromResponse, fromDependedOn) { var replaceWith = localStorage.getItem(responseArguments[0]); if (replaceWith) { replaceWith = replaceWith.toUpperCase(); - responseHeader = inject_substitute(responseHeader, "name", replaceWith); + responseHeader = inject_substitute( + responseHeader, + "name", + replaceWith + ); responseHeader = responseHeader.split(" ")[0]; $("#page3").css("display", "none"); $("#page4").css("display", "block"); $("#page4 .customImgRow .imgRowInner p").html(""); $("#page4 .customImgRow .imgRowInner p").css("display", "block"); - $("#page4 .customImgRow .imgRowInner p").append(`${responseHeader}`); + $("#page4 .customImgRow .imgRowInner p").append( + `${responseHeader}` + ); responseOnGoing = true; hasNoResponse = false; // closeResponseTimeout = setTimeout(async () => { @@ -835,14 +935,21 @@ async function nextQuestion(goBack, goBackFromResponse, fromDependedOn) { showResponse(responseHeader, responseBody); } } else if ([4, 5, 6].includes(apiQues.type)) { - if (fullAnswerObject && (fullAnswerObject.response_header || fullAnswerObject.response_body)) { + if ( + fullAnswerObject && + (fullAnswerObject.response_header || fullAnswerObject.response_body) + ) { if (fullAnswerObject.response_arguments) { responseHeader = fullAnswerObject.response_header; var responseArguments = fullAnswerObject.response_arguments; responseArguments = JSON.parse(responseArguments); var replaceWith = localStorage.getItem(responseArguments[0]); replaceWith = replaceWith.toUpperCase(); - responseHeader = inject_substitute(responseHeader, "name", replaceWith); + responseHeader = inject_substitute( + responseHeader, + "name", + replaceWith + ); responseBody = fullAnswerObject.response_body; } else { responseHeader = fullAnswerObject.response_header; @@ -891,7 +998,10 @@ function showResponse(responseHead, responseBody, weatherQuestion) { $("#page5").css("display", "block"); if (responseHead) { $("#page5 .responseRow .responseInner .responseHead").html(""); - $("#page5 .responseRow .responseInner .responseHead").css("display", "block"); + $("#page5 .responseRow .responseInner .responseHead").css( + "display", + "block" + ); $("#page5 .responseRow .responseInner .responseHead").append(`

${responseHead}

`); @@ -900,7 +1010,10 @@ function showResponse(responseHead, responseBody, weatherQuestion) { } if (responseBody) { $("#page5 .responseRow .responseInner .responseBody").html(""); - $("#page5 .responseRow .responseInner .responseBody").css("display", "block"); + $("#page5 .responseRow .responseInner .responseBody").css( + "display", + "block" + ); $("#page5 .responseRow .responseInner .responseBody").append(`

${responseBody}

`); @@ -910,7 +1023,22 @@ function showResponse(responseHead, responseBody, weatherQuestion) { if (weatherQuestion) { $("#page5 #weatherApi").css("display", "block"); } + // Countdown timer logic for Quiz 2 + clearInterval(responseCountdownInterval); + let countdown = Math.ceil(closeResponseTimeoutCounter / 1000); + $("#responseCountdown").show().text(`Closing in ${countdown} seconds...`); + responseCountdownInterval = setInterval(function () { + countdown--; + if (countdown > 0) { + $("#responseCountdown").text(`Closing in ${countdown} seconds...`); + } else { + clearInterval(responseCountdownInterval); + $("#responseCountdown").hide(); + } + }, 1000); closeResponseTimeout = setTimeout(() => { + clearInterval(responseCountdownInterval); + $("#responseCountdown").hide(); closeResponse(); }, closeResponseTimeoutCounter); } @@ -919,6 +1047,8 @@ function showResponse(responseHead, responseBody, weatherQuestion) { function closeResponse() { responseOnGoing = false; hasNoResponse = true; + clearInterval(responseCountdownInterval); + $("#responseCountdown").hide(); $("#page5").css("display", "none"); $("#page4").css("display", "none"); $("#page3").css("display", "block"); @@ -938,6 +1068,8 @@ function closeResponse() { } // function closeResponse ends here async function askQuestion(totalQuizQuestions, counter, fromBack) { + // Always hide all answer rows before showing the current one + $(".answerRow").hide(); clearTimeout(timeout); clearTimeout(closeResponseTimeout); @@ -975,7 +1107,12 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { const userAnswerToDependedQuestion = dataToReturn.find(function (item) { return item.question.id == parseInt(dependedQuesId); }); - if (!userAnswerToDependedQuestion || !userAnswerToDependedQuestion.answer || userAnswerToDependedQuestion.answer?.toLowerCase() != wantedAnswer?.toLowerCase()) { + if ( + !userAnswerToDependedQuestion || + !userAnswerToDependedQuestion.answer || + userAnswerToDependedQuestion.answer?.toLowerCase() != + wantedAnswer?.toLowerCase() + ) { currentActiveAnswerType = null; isSkipStoreAnswer = true; currentQuestionCounter++; @@ -1010,7 +1147,8 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { $("#noteRow .noteTitle h4").html("- Scientific Note -"); } } else { - if (!$("#page3 .questionRow.mtb").hasClass("no-note")) $("#page3 .questionRow.mtb").addClass("no-note"); + if (!$("#page3 .questionRow.mtb").hasClass("no-note")) + $("#page3 .questionRow.mtb").addClass("no-note"); $("#noteRow").css("display", "none"); } // end of displaying note @@ -1027,17 +1165,21 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { } // displaying question $("#questionRow").css("display", "block"); - if (!$("#page3 .questionRow").hasClass("no-image")) $("#page3 .questionRow").addClass("no-image"); + if (!$("#page3 .questionRow").hasClass("no-image")) + $("#page3 .questionRow").addClass("no-image"); type = ques.type; if (ques.id == 1) { - if ($("#page3 .container").hasClass("mto")) $(".container").removeClass("mto"); + if ($("#page3 .container").hasClass("mto")) + $(".container").removeClass("mto"); $("#page3 .questionRow.mtb").removeClass("mtb"); $("#page3 .container").addClass("center-everything"); $("#identity").addClass("hide"); saveResponseInto = ques.save_response_into; } else { - if ($("#page3 .container").hasClass("center-everything")) $("#page3 .container").removeClass("center-everything"); - if (!$("#page3 .questionRow").hasClass("mtb")) $("#page3 .questionRow").addClass("mtb"); + if ($("#page3 .container").hasClass("center-everything")) + $("#page3 .container").removeClass("center-everything"); + if (!$("#page3 .questionRow").hasClass("mtb")) + $("#page3 .questionRow").addClass("mtb"); $("#page3 .container").addClass("mto"); $("#identity").removeClass("hide"); } @@ -1054,7 +1196,11 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { $("#typeText input").attr("id", ques.placeholder); if (alreadyAnswered && alreadyAnswered.answer) { $("#typeText input").val(alreadyAnswered.answer); - } else if (currenQuesAnswerObj && currenQuesAnswerObj.answer && !alreadyAnswered) { + } else if ( + currenQuesAnswerObj && + currenQuesAnswerObj.answer && + !alreadyAnswered + ) { $("#typeText input").val(currenQuesAnswerObj.answer); } else { if (ques.id == 14) { @@ -1074,7 +1220,11 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { if (alreadyAnswered && alreadyAnswered.answer) { $("#typeNum input").val(alreadyAnswered.answer); - } else if (currenQuesAnswerObj && currenQuesAnswerObj.answer && !alreadyAnswered) { + } else if ( + currenQuesAnswerObj && + currenQuesAnswerObj.answer && + !alreadyAnswered + ) { $("#typeNum input").val(currenQuesAnswerObj.answer); } if (ques.save_response_into) saveResponseInto = ques.save_response_into; @@ -1095,11 +1245,23 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { } }); if (alreadyAnswered && alreadyAnswered.answer) { - $(`#typeMcq button[data-val="${alreadyAnswered.answer}"]`).addClass("highlight"); - selectAlreadyMcqAnswered(`#typeMcq button[data-val="${alreadyAnswered.answer}"]`); - } else if (currenQuesAnswerObj && currenQuesAnswerObj.answer && !alreadyAnswered) { - $(`#typeMcq button[data-val="${currenQuesAnswerObj.answer}"]`).addClass("highlight"); - selectAlreadyMcqAnswered(`#typeMcq button[data-val="${currenQuesAnswerObj.answer}"]`); + $(`#typeMcq button[data-val="${alreadyAnswered.answer}"]`).addClass( + "highlight" + ); + selectAlreadyMcqAnswered( + `#typeMcq button[data-val="${alreadyAnswered.answer}"]` + ); + } else if ( + currenQuesAnswerObj && + currenQuesAnswerObj.answer && + !alreadyAnswered + ) { + $(`#typeMcq button[data-val="${currenQuesAnswerObj.answer}"]`).addClass( + "highlight" + ); + selectAlreadyMcqAnswered( + `#typeMcq button[data-val="${currenQuesAnswerObj.answer}"]` + ); } } // type 4 ends here else if (type == 5) { @@ -1111,22 +1273,43 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { ques.answers.forEach((val) => { if (val.answer && val.image && ques.image_width && ques.image_height) { $("#typeMcqi .answerInner").append(` -
-
`); - if (!$("#page3 .row.noteRow").hasClass("image-below")) $("#page3 .row.noteRow").addClass("image-below"); + if (!$("#page3 .row.noteRow").hasClass("image-below")) + $("#page3 .row.noteRow").addClass("image-below"); $("#page3 .questionRow").removeClass("no-image"); } }); if (alreadyAnswered && alreadyAnswered.answer) { - $(`#typeMcqi button[data-val="${alreadyAnswered.answer}"]`).addClass("highlight"); - selectAlreadyMcqiAnswered(`#typeMcqi button[data-val="${alreadyAnswered.answer}"]`); - } else if (currenQuesAnswerObj && currenQuesAnswerObj.answer && !alreadyAnswered) { - $(`#typeMcqi button[data-val="${currenQuesAnswerObj.answer}"]`).addClass("highlight"); - selectAlreadyMcqiAnswered(`#typeMcqi button[data-val="${currenQuesAnswerObj.answer}"]`); + $(`#typeMcqi button[data-val="${alreadyAnswered.answer}"]`).addClass( + "highlight" + ); + selectAlreadyMcqiAnswered( + `#typeMcqi button[data-val="${alreadyAnswered.answer}"]` + ); + } else if ( + currenQuesAnswerObj && + currenQuesAnswerObj.answer && + !alreadyAnswered + ) { + $(`#typeMcqi button[data-val="${currenQuesAnswerObj.answer}"]`).addClass( + "highlight" + ); + selectAlreadyMcqiAnswered( + `#typeMcqi button[data-val="${currenQuesAnswerObj.answer}"]` + ); } } // type 5 ends here else if (type == 6) { @@ -1161,11 +1344,14 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { width: val.image.width, height: val.image.height, }; - if (!$("#page3 .row.noteRow").hasClass("image-below")) $("#page3 .row.noteRow").addClass("image-below"); + if (!$("#page3 .row.noteRow").hasClass("image-below")) + $("#page3 .row.noteRow").addClass("image-below"); $("#page3 .questionRow").removeClass("no-image"); if (index == 0) { $("#typeSlide .answerInner .imgDiv").css("display", "block"); - $("#typeSlide .answerInner .imgDiv").append(`Image missing`); + $("#typeSlide .answerInner .imgDiv").append( + `Image missing` + ); } } else { $("#page3 .row.noteRow").removeClass("image-below"); @@ -1175,15 +1361,23 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { max: minStep + incremental, image: hasImage, answer: val.answer, - black_list_actives: val.black_list_actives ? JSON.parse(val.black_list_actives) : [], + black_list_actives: val.black_list_actives + ? JSON.parse(val.black_list_actives) + : [], output_var: ques.output_variable_name, weight: ques.weight, - extra_var: ques.extra_output_variable ? JSON.parse(ques.extra_output_variable) : [], + extra_var: ques.extra_output_variable + ? JSON.parse(ques.extra_output_variable) + : [], }); //add ranges $("#typeSlide .answerInner .sliderRanges").append(` -
+
${val.hide_answer == 1 ? "" : val.answer}
`); @@ -1191,14 +1385,24 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { }); if (!atleastOneImage) { - if (!$("#page3 .questionRow").hasClass("no-image")) $("#page3 .questionRow").addClass("no-image"); + if (!$("#page3 .questionRow").hasClass("no-image")) + $("#page3 .questionRow").addClass("no-image"); } - $(".sliderRanges div").css("width", `${parseFloat(1 / ques.answers.length) * 100}%`); + $(".sliderRanges div").css( + "width", + `${parseFloat(1 / ques.answers.length) * 100}%` + ); if (alreadyAnswered && alreadyAnswered.answer) { $(`#typeSlide #myRange`).val(parseFloat(alreadyAnswered.slider_value)); $("#myRange").trigger("input", [true]); - } else if (currenQuesAnswerObj && currenQuesAnswerObj.answer && !alreadyAnswered) { - $(`#typeSlide #myRange`).val(parseFloat(currenQuesAnswerObj.slider_value)); + } else if ( + currenQuesAnswerObj && + currenQuesAnswerObj.answer && + !alreadyAnswered + ) { + $(`#typeSlide #myRange`).val( + parseFloat(currenQuesAnswerObj.slider_value) + ); $("#myRange").trigger("input", [true]); } } // type 6 ends here @@ -1211,25 +1415,39 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { if (val.answer) { $("#typeSelection .answerInner").append(`
- +
`); } }); + // Add 'None of the above' button + $("#typeSelection .answerInner").append(` +
+ +
+ `); if (alreadyAnswered && alreadyAnswered.answer) { if (Array.isArray(alreadyAnswered.answer)) { alreadyAnswered.answer.forEach((answer) => { if (!["Banana", "Olive", "Sunflowers"].includes(answer)) { - $(`#typeSelection button[data-val="${answer}"]`).trigger("click", [true]); + $(`#typeSelection button[data-val="${answer}"]`).trigger("click", [ + true, + ]); } }); } - } else if (currenQuesAnswerObj && currenQuesAnswerObj.answer && !alreadyAnswered) { + } else if ( + currenQuesAnswerObj && + currenQuesAnswerObj.answer && + !alreadyAnswered + ) { if (Array.isArray(currenQuesAnswerObj.answer)) { currenQuesAnswerObj.answer.forEach((answer) => { if (!["Banana", "Olive", "Sunflowers"].includes(answer)) { - $(`#typeSelection button[data-val="${answer}"]`).trigger("click", [true]); + $(`#typeSelection button[data-val="${answer}"]`).trigger("click", [ + true, + ]); } }); } @@ -1244,7 +1462,11 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { if (alreadyAnswered && alreadyAnswered.answer) { $("#typeGeo input#city").val(alreadyAnswered.answer); $("#typeGeo #city_id").val(alreadyAnswered.city_id); - } else if (currenQuesAnswerObj && currenQuesAnswerObj.answer && !alreadyAnswered) { + } else if ( + currenQuesAnswerObj && + currenQuesAnswerObj.answer && + !alreadyAnswered + ) { $("#typeGeo input#city").val(currenQuesAnswerObj.answer); $("#typeGeo #city_id").val(currenQuesAnswerObj.city_id); } @@ -1261,6 +1483,8 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) { $("#questionRow h1").html(ques.question); } currentQuestionCounter++; + // At the end of askQuestion, always update the nav bar + renderQuestionNavBar(); } async function storeAnswer(currentQuestion, currentActiveAnswerType) { @@ -1285,12 +1509,18 @@ async function storeAnswer(currentQuestion, currentActiveAnswerType) { dataToReturn.push(temp); } else { const dependedOnQuestions = dataToReturn.filter((ansObj, index) => { - if (ansObj.question.depends_on && ansObj.question.depends_on.split("|")[0] == temp["question"].id) { + if ( + ansObj.question.depends_on && + ansObj.question.depends_on.split("|")[0] == temp["question"].id + ) { ansObj.obj_index = index; return ansObj; } }); - if (dependedOnQuestions && temp["answer"] !== dataToReturn[answerExists].answer) { + if ( + dependedOnQuestions && + temp["answer"] !== dataToReturn[answerExists].answer + ) { dependedOnQuestions.forEach((dq) => { dataToReturn.splice(dq.obj_index, 1); }); @@ -1328,12 +1558,18 @@ async function storeAnswer(currentQuestion, currentActiveAnswerType) { dataToReturn.push(temp); } else { const dependedOnQuestions = dataToReturn.filter((ansObj, index) => { - if (ansObj.question.depends_on && ansObj.question.depends_on.split("|")[0] == temp["question"].id) { + if ( + ansObj.question.depends_on && + ansObj.question.depends_on.split("|")[0] == temp["question"].id + ) { ansObj.obj_index = index; return ansObj; } }); - if (dependedOnQuestions && temp["answer"] !== dataToReturn[answerExists].answer) { + if ( + dependedOnQuestions && + temp["answer"] !== dataToReturn[answerExists].answer + ) { dependedOnQuestions.forEach((dq) => { dataToReturn.splice(dq.obj_index, 1); }); @@ -1367,12 +1603,18 @@ async function storeAnswer(currentQuestion, currentActiveAnswerType) { dataToReturn.push(temp); } else { const dependedOnQuestions = dataToReturn.filter((ansObj, index) => { - if (ansObj.question.depends_on && ansObj.question.depends_on.split("|")[0] == temp["question"].id) { + if ( + ansObj.question.depends_on && + ansObj.question.depends_on.split("|")[0] == temp["question"].id + ) { ansObj.obj_index = index; return ansObj; } }); - if (dependedOnQuestions && temp["answer"] !== dataToReturn[answerExists].answer) { + if ( + dependedOnQuestions && + temp["answer"] !== dataToReturn[answerExists].answer + ) { dependedOnQuestions.forEach((dq) => { dataToReturn.splice(dq.obj_index, 1); }); @@ -1406,12 +1648,18 @@ async function storeAnswer(currentQuestion, currentActiveAnswerType) { dataToReturn.push(temp); } else { const dependedOnQuestions = dataToReturn.filter((ansObj, index) => { - if (ansObj.question.depends_on && ansObj.question.depends_on.split("|")[0] == temp["question"].id) { + if ( + ansObj.question.depends_on && + ansObj.question.depends_on.split("|")[0] == temp["question"].id + ) { ansObj.obj_index = index; return ansObj; } }); - if (dependedOnQuestions && temp["answer"] !== dataToReturn[answerExists].answer) { + if ( + dependedOnQuestions && + temp["answer"] !== dataToReturn[answerExists].answer + ) { dependedOnQuestions.forEach((dq) => { dataToReturn.splice(dq.obj_index, 1); }); @@ -1431,12 +1679,18 @@ async function storeAnswer(currentQuestion, currentActiveAnswerType) { dataToReturn.push(temp); } else { const dependedOnQuestions = dataToReturn.filter((ansObj, index) => { - if (ansObj.question.depends_on && ansObj.question.depends_on.split("|")[0] == temp["question"].id) { + if ( + ansObj.question.depends_on && + ansObj.question.depends_on.split("|")[0] == temp["question"].id + ) { ansObj.obj_index = index; return ansObj; } }); - if (dependedOnQuestions && temp["answer"] !== dataToReturn[answerExists].answer) { + if ( + dependedOnQuestions && + temp["answer"] !== dataToReturn[answerExists].answer + ) { dependedOnQuestions.forEach((dq) => { dataToReturn.splice(dq.obj_index, 1); }); @@ -1454,12 +1708,18 @@ async function storeAnswer(currentQuestion, currentActiveAnswerType) { dataToReturn.push(temp); } else { const dependedOnQuestions = dataToReturn.filter((ansObj, index) => { - if (ansObj.question.depends_on && ansObj.question.depends_on.split("|")[0] == temp["question"].id) { + if ( + ansObj.question.depends_on && + ansObj.question.depends_on.split("|")[0] == temp["question"].id + ) { ansObj.obj_index = index; return ansObj; } }); - if (dependedOnQuestions && temp["answer"] !== dataToReturn[answerExists].answer) { + if ( + dependedOnQuestions && + temp["answer"] !== dataToReturn[answerExists].answer + ) { dependedOnQuestions.forEach((dq) => { dataToReturn.splice(dq.obj_index, 1); }); @@ -1475,7 +1735,11 @@ async function storeAnswer(currentQuestion, currentActiveAnswerType) { return false; } if (ans && !city_id) { - await fetch(url_preset + "/api/v1/places/autocomplete?input=" + ans.replace(/ /g, "")) + await fetch( + url_preset + + "/api/v1/places/autocomplete?input=" + + ans.replace(/ /g, "") + ) .then((res) => res.json()) .then(function (data) { city_id = data[0].id; @@ -1483,11 +1747,15 @@ async function storeAnswer(currentQuestion, currentActiveAnswerType) { } try { if (!$(".lds-ring").hasClass("active")) $(".lds-ring").addClass("active"); - const payload = await fetch(url_preset + `/api/v1/weather-profile?city_id=${city_id}`).then((response) => response.json()); + const payload = await fetch( + url_preset + `/api/v1/weather-profile?city_id=${city_id}` + ).then((response) => response.json()); if (payload.success && payload.data) { temp["weights"] = payload.data.weights; $("#humidity .info-value").html(payload.data.humidity); - $("#temp .info-value").html(`${payload.data.temperature}${payload.data.unit}`); + $("#temp .info-value").html( + `${payload.data.temperature}${payload.data.unit}` + ); $("#sun .info-value").html(payload.data.sun); $("#pollution .info-value").html(payload.data.pollution); } else { @@ -1509,12 +1777,18 @@ async function storeAnswer(currentQuestion, currentActiveAnswerType) { dataToReturn.push(temp); } else { const dependedOnQuestions = dataToReturn.filter((ansObj, index) => { - if (ansObj.question.depends_on && ansObj.question.depends_on.split("|")[0] == temp["question"].id) { + if ( + ansObj.question.depends_on && + ansObj.question.depends_on.split("|")[0] == temp["question"].id + ) { ansObj.obj_index = index; return ansObj; } }); - if (dependedOnQuestions && temp["answer"] !== dataToReturn[answerExists].answer) { + if ( + dependedOnQuestions && + temp["answer"] !== dataToReturn[answerExists].answer + ) { dependedOnQuestions.forEach((dq) => { dataToReturn.splice(dq.obj_index, 1); }); @@ -1524,6 +1798,20 @@ async function storeAnswer(currentQuestion, currentActiveAnswerType) { } } localStorage.setItem("answers", JSON.stringify(dataToReturn)); + if ( + typeof customerEmail !== "undefined" && + customerEmail && + customerEmail.innerText + ) { + localStorage.setItem( + "answers_" + customerEmail.innerText, + JSON.stringify(dataToReturn) + ); + } + let userKey = getUserProgressKey(); + localStorage.setItem(userKey, JSON.stringify(dataToReturn)); + checkResumeButtonVisibility(); + renderQuestionNavBar(); } let currentSuggestIndex; @@ -1532,7 +1820,10 @@ let itemSelected = false; let enterOnce = false; $(document).on("click focus", async function (event) { - if (!event.target.closest("#result") && !event.target.closest("#typeGeo input")) { + if ( + !event.target.closest("#result") && + !event.target.closest("#typeGeo input") + ) { $("#result").css({ display: "none", }); @@ -1573,7 +1864,9 @@ $("#typeGeo input").on("keyup", function (evt) { return nextQuestion(); } $("#typeGeo input").val($("#suggestion-list li.active.selected").text()); - $("#typeGeo #city_id").val($("#suggestion-list li.active.selected").attr("data-place-id")); + $("#typeGeo #city_id").val( + $("#suggestion-list li.active.selected").attr("data-place-id") + ); $("#result").css({ display: "none", }); @@ -1593,13 +1886,19 @@ $("#typeGeo input").on("keyup", function (evt) { currentSuggestIndex = 1; } } else if (evt.key == "ArrowUp") { - currentSuggestIndex = currentSuggestIndex ? currentSuggestIndex - 1 : listLength; + currentSuggestIndex = currentSuggestIndex + ? currentSuggestIndex - 1 + : listLength; if (currentSuggestIndex < 1) { currentSuggestIndex = listLength; } } - $(`#suggestion-list li:nth-child(${currentSuggestIndex})`).addClass("active"); - $(`#suggestion-list li:nth-child(${currentSuggestIndex})`).addClass("selected"); + $(`#suggestion-list li:nth-child(${currentSuggestIndex})`).addClass( + "active" + ); + $(`#suggestion-list li:nth-child(${currentSuggestIndex})`).addClass( + "selected" + ); return false; } @@ -1616,11 +1915,18 @@ $("#typeGeo input").on("keyup", function (evt) { return; } let list = ""; - fetch(url_preset + "/api/v1/places/autocomplete?input=" + val.replace(/ /g, "")) + fetch( + url_preset + "/api/v1/places/autocomplete?input=" + val.replace(/ /g, "") + ) .then((res) => res.json()) .then(function (data) { for (i = 0; i < data.length; i++) { - list += `
  • ` + data[i].name + "
  • "; + list += + `
  • ` + + data[i].name + + "
  • "; } res.html(``); return true; @@ -1656,7 +1962,9 @@ $(document).on("input", "#myRange", async function (event, isCustom) { sliderBLActives = currRange.black_list_actives; if (currRange.image) { if ($("#typeSlide .answerInner .imgDiv img").length == 0) { - $("#typeSlide .answerInner .imgDiv").append(`Image missing`); + $("#typeSlide .answerInner .imgDiv").append( + `Image missing` + ); } else { $("#typeSlide .answerInner .imgDiv img").attr("id", currRange.image.id); $("#typeSlide .answerInner .imgDiv img").attr("src", currRange.image.url); @@ -1742,7 +2050,9 @@ async function addToCart() { if (response.ok && data) { const products = data.products; existingProducts = products.filter((product) => { - let inFinalList = finalActives.find((active) => active[0] == product.title); + let inFinalList = finalActives.find( + (active) => active[0] == product.title + ); if (inFinalList) { product.score = inFinalList[1]; return product; @@ -1754,7 +2064,9 @@ async function addToCart() { lineItems.push({ id: prod.variants[0].id, quantity: 1, - properties: { score: prod.score ? parseFloat(prod.score).toFixed(2) : -1 }, + properties: { + score: prod.score ? parseFloat(prod.score).toFixed(2) : -1, + }, }); // } }); @@ -1802,3 +2114,509 @@ function handleNoneOfTheAbove() { function handleImageMissing(self) { $(self).addClass("image-missing"); } + +// 1. Add checkAllergie function near the top (after variable declarations) +function checkAllergie(btn) { + clearTimeout(timeout); + var val = $(btn).attr("data-val"); + // Quiz 4: Terminate if Banana, Olive, or Sunflowers is selected + if (["Banana", "Olive", "Sunflowers"].includes(val)) { + showTerminationScreen(); + return; + } + if ($(btn).hasClass("active")) { + tempSelectionAns.splice(tempSelectionAns.indexOf(val), 1); + $(btn).removeClass("active"); + $(btn).removeClass("highlight"); + } else { + tempSelectionAns.push(val); + if (!$(btn).hasClass("active")) $(btn).addClass("active"); + if (!$(btn).hasClass("highlight")) $(btn).addClass("highlight"); + } + timeout = setTimeout(function () { + nextQuestion(); + }, selectionQuestionTimeoutCounter); +} + +// Quiz 4: Show termination overlay and handle countdown/redirect +function showTerminationScreen() { + // Get message and counter from mainConfigurations (from /configurations API) + var message = + mainConfigurations && mainConfigurations.termination_message + ? mainConfigurations.termination_message + : "You have selected an allergen. The quiz will now end."; + var counter = + mainConfigurations && mainConfigurations.termination_counter + ? parseInt(mainConfigurations.termination_counter) + : 5; + $("#terminationMessage").text(message); + $("#terminationCountdown").text(counter); + $("#terminationOverlay").css({ display: "flex" }); + var countdown = counter; + var interval = setInterval(function () { + countdown--; + if (countdown > 0) { + $("#terminationCountdown").text(countdown); + } else { + clearInterval(interval); + window.location.href = "/"; + } + }, 1000); +} + +// Quiz 5: Show Resume Quiz button if progress exists, and handle resume logic +$(document).ready(function () { + // Use email as key if available, otherwise fallback to local + let userKey = null; + if ( + typeof customerEmail !== "undefined" && + customerEmail && + customerEmail.innerText + ) { + userKey = "answers_" + customerEmail.innerText; + } + let savedAnswers = userKey + ? localStorage.getItem(userKey) + : localStorage.getItem("answers"); + if (savedAnswers && JSON.parse(savedAnswers).length > 0) { + $("#resumeButton").show(); + } + + $("#resumeButton").on("click", async function () { + // Load saved progress + let answers = userKey + ? localStorage.getItem(userKey) + : localStorage.getItem("answers"); + if (answers) { + dataToReturn = JSON.parse(answers); + // Find last answered question + let lastQ = dataToReturn[dataToReturn.length - 1]; + // Set quiz and question index + let found = false; + for (let i = 0; i < allItems.length; i++) { + let idx = allItems[i].questions.findIndex( + (q) => q.id === lastQ.question.id + ); + if (idx !== -1) { + currentQuizIndex = i; + currentQuestionCounter = idx + 1; + found = true; + break; + } + } + if (!found) { + currentQuizIndex = 0; + currentQuestionCounter = 0; + } + $("#page1").css("display", "none"); + $("#page2").css("display", "none"); + $("#page3").css("display", "none"); + $("#page4").css("display", "none"); + $("#page5").css("display", "none"); + $("#page6").css("display", "none"); + $("#page7").css("display", "none"); + await getQuizzesApi(); + showQuizTitle(); + // Resume from next unanswered question + return askQuestion( + allItems[currentQuizIndex].questions, + currentQuestionCounter + ); + } + }); +}); + +// Utility for user-specific progress key +function getUserProgressKey() { + if ( + typeof customerEmail !== "undefined" && + customerEmail && + customerEmail.innerText + ) { + return "answers_" + customerEmail.innerText; + } + return "answers"; +} +function clearAllProgress() { + localStorage.removeItem("answers"); + if ( + typeof customerEmail !== "undefined" && + customerEmail && + customerEmail.innerText + ) { + localStorage.removeItem("answers_" + customerEmail.innerText); + } +} + +// Overwrite reset logic +$(document).on("click", "#resetQuizButton", function () { + if ( + confirm( + "Are you sure you want to reset the quiz? All progress will be lost." + ) + ) { + clearAllProgress(); + // Reload the page for a true fresh start (clears all in-memory state/UI) + window.location.reload(); + } +}); + +// Overwrite resume logic +$(document).ready(function () { + let userKey = getUserProgressKey(); + let savedAnswers = localStorage.getItem(userKey); + if (savedAnswers && JSON.parse(savedAnswers).length > 0) { + $("#resumeButton").show(); + } + $("#resumeButton") + .off("click") + .on("click", async function () { + let userKey = getUserProgressKey(); + let answers = localStorage.getItem(userKey); + let navState = localStorage.getItem("quiz_nav_state"); + await getQuizzesApi(); // Always load quizzes first + let startFromBeginning = false; + let found = false; + if (answers) { + try { + dataToReturn = JSON.parse(answers); + } catch (e) { + dataToReturn = []; + } + if (Array.isArray(dataToReturn) && dataToReturn.length > 0) { + let lastQ = dataToReturn[dataToReturn.length - 1]; + if ( + lastQ && + lastQ.question && + typeof lastQ.question.id !== "undefined" + ) { + for (let i = 0; i < allItems.length; i++) { + let idx = allItems[i].questions.findIndex( + (q) => q.id === lastQ.question.id + ); + if (idx !== -1) { + currentQuizIndex = i; + currentQuestionCounter = idx + 1; + found = true; + break; + } + } + } + } + } + // If not found by answers, try nav state + if (!found && navState) { + try { + const { quizIndex, questionCounter } = JSON.parse(navState); + if ( + typeof quizIndex === "number" && + typeof questionCounter === "number" + ) { + currentQuizIndex = quizIndex; + currentQuestionCounter = questionCounter; + found = true; + } + } catch (e) {} + } + // If still not found, start from beginning + if (!found) { + currentQuizIndex = 0; + currentQuestionCounter = 0; + } + $("#page1").css("display", "none"); + $("#page2").css("display", "none"); + $("#page3").css("display", "none"); + $("#page4").css("display", "none"); + $("#page5").css("display", "none"); + $("#page6").css("display", "none"); + $("#page7").css("display", "none"); + showQuizTitle(); + askQuestion(allItems[currentQuizIndex].questions, currentQuestionCounter); + }); +}); + +// In storeAnswer, always save to the correct user key +async function storeAnswer(currentQuestion, currentActiveAnswerType) { + // ... existing code ... + let userKey = getUserProgressKey(); + localStorage.setItem(userKey, JSON.stringify(dataToReturn)); + checkResumeButtonVisibility(); + renderQuestionNavBar(); +} + +function renderQuestionNavBar() { + if (!allItems || allItems.length === 0 || !$("#page3").is(":visible")) { + $("#questionNavBar").hide(); + return; + } + let questions = []; + allItems.forEach((quiz) => { + quiz.questions.forEach((q) => { + questions.push({ id: q.id, text: q.question }); + }); + }); + let answeredIds = (dataToReturn || []) + .map((a) => a.question && a.question.id) + .filter(Boolean); + // Determine the current question id + let currentId = null; + if ( + allItems[currentQuizIndex] && + allItems[currentQuizIndex].questions[currentQuestionCounter] // currentQuestionCounter points to the next question, so use currentQuestionCounter-1 if >0 + ) { + currentId = + allItems[currentQuizIndex].questions[currentQuestionCounter]?.id; + // If currentId is undefined (e.g., at end), fallback to previous + if (!currentId && currentQuestionCounter > 0) { + currentId = + allItems[currentQuizIndex].questions[currentQuestionCounter - 1]?.id; + } + } else if ( + allItems[currentQuizIndex] && + allItems[currentQuizIndex].questions[currentQuestionCounter - 1] + ) { + currentId = + allItems[currentQuizIndex].questions[currentQuestionCounter - 1].id; + } + let html = ""; + questions.forEach((q, idx) => { + let btnClass = "nav-btn"; + const isAnswered = answeredIds.includes(q.id); + const isCurrent = q.id === currentId; + if (isAnswered) btnClass += " answered"; + if (isCurrent) btnClass += " current"; + if (!isAnswered) btnClass += " unanswered"; + html += ``; + }); + $("#questionNavBar").html(html).show(); +} + +// Handle nav bar button click +$(document).on("click", "#questionNavBar .nav-btn", function () { + let qid = parseInt($(this).attr("data-qid")); + let found = false; + for (let i = 0; i < allItems.length; i++) { + let idx = allItems[i].questions.findIndex((q) => q.id === qid); + if (idx !== -1) { + currentQuizIndex = i; + currentQuestionCounter = idx; + found = true; + break; + } + } + if (found) { + askQuestion(allItems[currentQuizIndex].questions, currentQuestionCounter); + } +}); + +// Update nav bar on question change +let origAskQuestion = askQuestion; +askQuestion = async function (...args) { + let result = await origAskQuestion.apply(this, args); + renderQuestionNavBar(); + return result; +}; + +// Show/hide nav bar on page changes +function updateNavBarVisibility() { + if ( + typeof renderQuestionNavBar === "function" && + $("#page3").is(":visible") + ) { + renderQuestionNavBar(); + $("#questionNavBar").show(); + } else { + $("#questionNavBar").hide(); + } +} +// Ensure nav bar is shown after every askQuestion +if (!window._quizNavWrapped) { + window._quizNavWrapped = true; + const origAskQuestion = askQuestion; + askQuestion = async function (...args) { + let result = await origAskQuestion.apply(this, args); + updateNavBarVisibility(); + saveNavState(); + return result; + }; +} +// On page load or resume, restore nav state and show nav bar if on question page +$(document).ready(function () { + loadNavState(); + updateNavBarVisibility(); +}); + +// Add minimal CSS for nav bar button states +$( + "" +).appendTo("head"); + +// Utility for nav state persistence +function saveNavState() { + localStorage.setItem( + "quiz_nav_state", + JSON.stringify({ + quizIndex: currentQuizIndex, + questionCounter: currentQuestionCounter, + }) + ); +} +function loadNavState() { + const state = localStorage.getItem("quiz_nav_state"); + if (state) { + try { + const { quizIndex, questionCounter } = JSON.parse(state); + if ( + typeof quizIndex === "number" && + typeof questionCounter === "number" + ) { + currentQuizIndex = quizIndex; + currentQuestionCounter = questionCounter; + } + } catch (e) {} + } +} + +// On reset, clear nav state +function clearAllProgress() { + localStorage.removeItem("answers"); + localStorage.removeItem("quiz_nav_state"); + if ( + typeof customerEmail !== "undefined" && + customerEmail && + customerEmail.innerText + ) { + localStorage.removeItem("answers_" + customerEmail.innerText); + } + $("#resumeButton").hide(); +} + +// BEGIN button: always start fresh and clear progress +$(document).on("click", "#beginButton", async function () { + clearAllProgress(); + $("#resumeButton").hide(); + $("#page1").css("display", "none"); + $("#page2").css("display", "none"); + $("#page3").css("display", "none"); + $("#page4").css("display", "none"); + $("#page5").css("display", "none"); + $("#page6").css("display", "none"); + $("#page7").css("display", "none"); + dataToReturn = []; + uniqueQuestionsShowed = []; + lastQuizResponseShown = null; + lastShowedQuestionId = null; + currentQuizIndex = 0; + currentQuestionCounter = 0; + isExecuted = false; + await getQuizzesApi(); + showQuizTitle(); + askQuestion(allItems[currentQuizIndex].questions, 0); +}); + +// Resume button logic: only show if there is progress +function checkResumeButtonVisibility() { + let userKey = getUserProgressKey(); + let savedAnswers = localStorage.getItem(userKey); + let navState = localStorage.getItem("quiz_nav_state"); + if ((savedAnswers && JSON.parse(savedAnswers).length > 0) || navState) { + $("#resumeButton").show(); + } else { + $("#resumeButton").hide(); + } +} + +$(document).ready(function () { + loadNavState(); + updateNavBarVisibility(); + checkResumeButtonVisibility(); + $("#resumeButton") + .off("click") + .on("click", async function () { + let userKey = getUserProgressKey(); + let answers = localStorage.getItem(userKey); + let navState = localStorage.getItem("quiz_nav_state"); + await getQuizzesApi(); // Always load quizzes first + let startFromBeginning = false; + let found = false; + if (answers) { + try { + dataToReturn = JSON.parse(answers); + } catch (e) { + dataToReturn = []; + } + if (Array.isArray(dataToReturn) && dataToReturn.length > 0) { + let lastQ = dataToReturn[dataToReturn.length - 1]; + if ( + lastQ && + lastQ.question && + typeof lastQ.question.id !== "undefined" + ) { + for (let i = 0; i < allItems.length; i++) { + let idx = allItems[i].questions.findIndex( + (q) => q.id === lastQ.question.id + ); + if (idx !== -1) { + currentQuizIndex = i; + currentQuestionCounter = idx + 1; + found = true; + break; + } + } + } + } + } + // If not found by answers, try nav state + if (!found && navState) { + try { + const { quizIndex, questionCounter } = JSON.parse(navState); + if ( + typeof quizIndex === "number" && + typeof questionCounter === "number" + ) { + currentQuizIndex = quizIndex; + currentQuestionCounter = questionCounter; + found = true; + } + } catch (e) {} + } + // If still not found, start from beginning + if (!found) { + currentQuizIndex = 0; + currentQuestionCounter = 0; + } + $("#page1").css("display", "none"); + $("#page2").css("display", "none"); + $("#page3").css("display", "none"); + $("#page4").css("display", "none"); + $("#page5").css("display", "none"); + $("#page6").css("display", "none"); + $("#page7").css("display", "none"); + showQuizTitle(); + askQuestion(allItems[currentQuizIndex].questions, currentQuestionCounter); + }); +}); + +// After reset, hide resume button until new progress is made +function clearAllProgress() { + localStorage.removeItem("answers"); + localStorage.removeItem("quiz_nav_state"); + if ( + typeof customerEmail !== "undefined" && + customerEmail && + customerEmail.innerText + ) { + localStorage.removeItem("answers_" + customerEmail.innerText); + } + $("#resumeButton").hide(); +} diff --git a/public/quiz-test.html b/public/quiz-test.html index b09189a..996e8ba 100644 --- a/public/quiz-test.html +++ b/public/quiz-test.html @@ -23,10 +23,15 @@ Let’s start our journey just for you. -

    - We are experts on skin and skincare actives.. -

    +

    We are experts on skin and skincare actives..

    +
    @@ -46,18 +51,52 @@
    - @@ -112,7 +155,14 @@
    - +
    @@ -121,7 +171,11 @@
    -
    +
    @@ -133,7 +187,9 @@
    - +
    @@ -143,16 +199,28 @@
    -