diff --git a/package-lock.json b/package-lock.json index bf8401f585cf13c85d81e6a8f01912a151578266..8128c7cae624745f25207e7ac2bf07f290c690ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "roboto-fontface": "*", "sockjs-client": "^1.6.0", "stompjs": "^2.3.3", + "tw-elements": "^1.0.0-alpha12", "vue": "^3.2.13", "vue-router": "^4.0.3", "vuelidate": "^0.7.7", @@ -2381,7 +2382,6 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -2393,7 +2393,6 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -2401,7 +2400,6 @@ }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -2416,6 +2414,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@popperjs/core": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", + "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@sideway/address": { "version": "4.1.4", "dev": true, @@ -3865,7 +3872,6 @@ }, "node_modules/acorn-node": { "version": "1.8.2", - "dev": true, "license": "Apache-2.0", "dependencies": { "acorn": "^7.0.0", @@ -3875,7 +3881,6 @@ }, "node_modules/acorn-node/node_modules/acorn": { "version": "7.4.1", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -3886,7 +3891,6 @@ }, "node_modules/acorn-node/node_modules/acorn-walk": { "version": "7.2.0", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -4037,7 +4041,6 @@ }, "node_modules/anymatch": { "version": "3.1.2", - "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -4068,7 +4071,6 @@ }, "node_modules/arg": { "version": "5.0.1", - "dev": true, "license": "MIT" }, "node_modules/argparse": { @@ -4436,7 +4438,6 @@ }, "node_modules/binary-extensions": { "version": "2.2.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4525,7 +4526,6 @@ }, "node_modules/braces": { "version": "3.0.2", - "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.0.1" @@ -4666,7 +4666,6 @@ }, "node_modules/camelcase-css": { "version": "2.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -4735,9 +4734,42 @@ "node": ">=6" } }, + "node_modules/chart.js": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz", + "integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==", + "dependencies": { + "chartjs-color": "^2.1.0", + "moment": "^2.10.2" + } + }, + "node_modules/chartjs-color": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", + "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", + "dependencies": { + "chartjs-color-string": "^0.6.0", + "color-convert": "^1.9.3" + } + }, + "node_modules/chartjs-color-string": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", + "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", + "dependencies": { + "color-name": "^1.0.0" + } + }, + "node_modules/chartjs-plugin-datalabels": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-0.7.0.tgz", + "integrity": "sha512-PKVUX14nYhH0wcdCpgOoC39Gbzvn6cZ7O9n+bwc02yKD9FTnJ7/TSrBcfebmolFZp1Rcicr9xbT0a5HUbigS7g==", + "peerDependencies": { + "chart.js": ">= 2.7.0 < 3" + } + }, "node_modules/chokidar": { "version": "3.5.3", - "dev": true, "funding": [ { "type": "individual", @@ -4763,7 +4795,6 @@ }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -4983,7 +5014,6 @@ }, "node_modules/color-convert": { "version": "1.9.3", - "dev": true, "license": "MIT", "dependencies": { "color-name": "1.1.3" @@ -4991,7 +5021,6 @@ }, "node_modules/color-name": { "version": "1.1.3", - "dev": true, "license": "MIT" }, "node_modules/colord": { @@ -5498,7 +5527,6 @@ }, "node_modules/cssesc": { "version": "3.0.0", - "dev": true, "license": "MIT", "bin": { "cssesc": "bin/cssesc" @@ -5615,6 +5643,11 @@ "version": "2.6.20", "license": "MIT" }, + "node_modules/custom-event-polyfill": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz", + "integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==" + }, "node_modules/d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -5837,7 +5870,6 @@ }, "node_modules/defined": { "version": "1.0.0", - "dev": true, "license": "MIT" }, "node_modules/delayed-stream": { @@ -5861,6 +5893,14 @@ "dev": true, "license": "MIT" }, + "node_modules/detect-autofill": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/detect-autofill/-/detect-autofill-1.1.4.tgz", + "integrity": "sha512-utCBQwCR/beSnADQmBC7C4tTueBBkYCl6WSpfGUkYKO/+MzPxqYGj6G4MvHzcKmH1gCTK+VunX2vaagvkRXPvA==", + "dependencies": { + "custom-event-polyfill": "^1.0.7" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "dev": true, @@ -5876,7 +5916,6 @@ }, "node_modules/detective": { "version": "5.2.0", - "dev": true, "license": "MIT", "dependencies": { "acorn-node": "^1.6.1", @@ -5892,7 +5931,6 @@ }, "node_modules/didyoumean": { "version": "1.2.2", - "dev": true, "license": "Apache-2.0" }, "node_modules/diff-sequences": { @@ -5916,7 +5954,6 @@ }, "node_modules/dlv": { "version": "1.1.3", - "dev": true, "license": "MIT" }, "node_modules/dns-equal": { @@ -7047,7 +7084,6 @@ }, "node_modules/fast-glob": { "version": "3.2.11", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -7062,7 +7098,6 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -7083,7 +7118,6 @@ }, "node_modules/fastq": { "version": "1.13.0", - "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -7131,7 +7165,6 @@ }, "node_modules/fill-range": { "version": "7.0.1", - "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -7300,7 +7333,6 @@ }, "node_modules/function-bind": { "version": "1.1.1", - "dev": true, "license": "MIT" }, "node_modules/functional-red-black-tree": { @@ -7377,7 +7409,6 @@ }, "node_modules/glob-parent": { "version": "6.0.2", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.3" @@ -7444,7 +7475,6 @@ }, "node_modules/has": { "version": "1.0.3", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.1" @@ -7858,7 +7888,6 @@ }, "node_modules/is-binary-path": { "version": "2.1.0", - "dev": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -7890,7 +7919,6 @@ }, "node_modules/is-core-module": { "version": "2.9.0", - "dev": true, "license": "MIT", "dependencies": { "has": "^1.0.3" @@ -7923,7 +7951,6 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7955,7 +7982,6 @@ }, "node_modules/is-glob": { "version": "4.0.3", - "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -7974,7 +8000,6 @@ }, "node_modules/is-number": { "version": "7.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -10322,7 +10347,6 @@ }, "node_modules/lilconfig": { "version": "2.0.5", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -10714,7 +10738,6 @@ }, "node_modules/merge2": { "version": "1.4.1", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -10730,7 +10753,6 @@ }, "node_modules/micromatch": { "version": "4.0.5", - "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.2", @@ -10863,7 +10885,6 @@ }, "node_modules/minimist": { "version": "1.2.6", - "dev": true, "license": "MIT" }, "node_modules/minipass": { @@ -10893,6 +10914,14 @@ "dev": true, "license": "MIT" }, + "node_modules/moment": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", + "engines": { + "node": "*" + } + }, "node_modules/mrmime": { "version": "1.0.0", "dev": true, @@ -11082,7 +11111,6 @@ }, "node_modules/normalize-path": { "version": "3.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11144,7 +11172,6 @@ }, "node_modules/object-hash": { "version": "3.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -11506,7 +11533,6 @@ }, "node_modules/path-parse": { "version": "1.0.7", - "dev": true, "license": "MIT" }, "node_modules/path-to-regexp": { @@ -11522,13 +11548,17 @@ "node": ">=8" } }, + "node_modules/perfect-scrollbar": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz", + "integrity": "sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g==" + }, "node_modules/picocolors": { "version": "1.0.0", "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -11556,6 +11586,16 @@ "node": ">=8" } }, + "node_modules/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/portfinder": { "version": "1.0.28", "dev": true, @@ -11688,7 +11728,6 @@ }, "node_modules/postcss-js": { "version": "4.0.0", - "dev": true, "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" @@ -11706,7 +11745,6 @@ }, "node_modules/postcss-load-config": { "version": "3.1.4", - "dev": true, "license": "MIT", "dependencies": { "lilconfig": "^2.0.5", @@ -11916,7 +11954,6 @@ }, "node_modules/postcss-nested": { "version": "5.0.6", - "dev": true, "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.0.6" @@ -12103,7 +12140,6 @@ }, "node_modules/postcss-selector-parser": { "version": "6.0.10", - "dev": true, "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -12144,7 +12180,6 @@ }, "node_modules/postcss-value-parser": { "version": "4.2.0", - "dev": true, "license": "MIT" }, "node_modules/prelude-ls": { @@ -12336,7 +12371,6 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", - "dev": true, "funding": [ { "type": "github", @@ -12355,7 +12389,6 @@ }, "node_modules/quick-lru": { "version": "5.1.1", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -12468,7 +12501,6 @@ }, "node_modules/readdirp": { "version": "3.6.0", - "dev": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -12598,7 +12630,6 @@ }, "node_modules/resolve": { "version": "1.22.0", - "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.8.1", @@ -12666,7 +12697,6 @@ }, "node_modules/reusify": { "version": "1.0.4", - "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -12693,7 +12723,6 @@ }, "node_modules/run-parallel": { "version": "1.2.0", - "dev": true, "funding": [ { "type": "github", @@ -13396,7 +13425,6 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -13479,7 +13507,6 @@ }, "node_modules/tailwindcss": { "version": "3.0.24", - "dev": true, "license": "MIT", "dependencies": { "arg": "^5.0.1", @@ -13517,7 +13544,6 @@ }, "node_modules/tailwindcss/node_modules/color-name": { "version": "1.1.4", - "dev": true, "license": "MIT" }, "node_modules/tapable": { @@ -13745,7 +13771,6 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", - "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -13834,6 +13859,21 @@ "dev": true, "license": "0BSD" }, + "node_modules/tw-elements": { + "version": "1.0.0-alpha12", + "resolved": "https://registry.npmjs.org/tw-elements/-/tw-elements-1.0.0-alpha12.tgz", + "integrity": "sha512-AQHwXIC4kw4T0NPKAi0vD1bkHSiA4RhdXqqnXDWEHKsrN02njc/ITB3YZ92s2f2jt+wBPI2UOpeUsWL5xiMVeQ==", + "dependencies": { + "@popperjs/core": "^2.6.0", + "chart.js": "^2.9.4", + "chartjs-plugin-datalabels": "^0.7.0", + "deepmerge": "^4.2.2", + "detect-autofill": "^1.1.3", + "perfect-scrollbar": "^1.5.0", + "popper.js": "^1.16.1", + "tailwindcss": "^3.0.7" + } + }, "node_modules/type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", @@ -13979,7 +14019,6 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", - "dev": true, "license": "MIT" }, "node_modules/utila": { @@ -14942,7 +14981,6 @@ }, "node_modules/xtend": { "version": "4.0.2", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4" @@ -14972,7 +15010,6 @@ }, "node_modules/yaml": { "version": "1.10.2", - "dev": true, "license": "ISC", "engines": { "node": ">= 6" @@ -16530,19 +16567,16 @@ }, "@nodelib/fs.scandir": { "version": "2.1.5", - "dev": true, "requires": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true + "version": "2.0.5" }, "@nodelib/fs.walk": { "version": "1.2.8", - "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -16552,6 +16586,11 @@ "version": "1.0.0-next.21", "dev": true }, + "@popperjs/core": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", + "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==" + }, "@sideway/address": { "version": "4.1.4", "dev": true, @@ -17594,7 +17633,6 @@ }, "acorn-node": { "version": "1.8.2", - "dev": true, "requires": { "acorn": "^7.0.0", "acorn-walk": "^7.0.0", @@ -17602,12 +17640,10 @@ }, "dependencies": { "acorn": { - "version": "7.4.1", - "dev": true + "version": "7.4.1" }, "acorn-walk": { - "version": "7.2.0", - "dev": true + "version": "7.2.0" } } }, @@ -17696,7 +17732,6 @@ }, "anymatch": { "version": "3.1.2", - "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -17707,8 +17742,7 @@ "dev": true }, "arg": { - "version": "5.0.1", - "dev": true + "version": "5.0.1" }, "argparse": { "version": "1.0.10", @@ -17935,8 +17969,7 @@ "dev": true }, "binary-extensions": { - "version": "2.2.0", - "dev": true + "version": "2.2.0" }, "bl": { "version": "4.1.0", @@ -18008,7 +18041,6 @@ }, "braces": { "version": "3.0.2", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -18085,8 +18117,7 @@ "dev": true }, "camelcase-css": { - "version": "2.0.1", - "dev": true + "version": "2.0.1" }, "caniuse-api": { "version": "3.0.0", @@ -18123,9 +18154,40 @@ "version": "0.2.0", "dev": true }, + "chart.js": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz", + "integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==", + "requires": { + "chartjs-color": "^2.1.0", + "moment": "^2.10.2" + } + }, + "chartjs-color": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", + "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", + "requires": { + "chartjs-color-string": "^0.6.0", + "color-convert": "^1.9.3" + } + }, + "chartjs-color-string": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", + "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", + "requires": { + "color-name": "^1.0.0" + } + }, + "chartjs-plugin-datalabels": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-0.7.0.tgz", + "integrity": "sha512-PKVUX14nYhH0wcdCpgOoC39Gbzvn6cZ7O9n+bwc02yKD9FTnJ7/TSrBcfebmolFZp1Rcicr9xbT0a5HUbigS7g==", + "requires": {} + }, "chokidar": { "version": "3.5.3", - "dev": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -18139,7 +18201,6 @@ "dependencies": { "glob-parent": { "version": "5.1.2", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -18280,14 +18341,12 @@ }, "color-convert": { "version": "1.9.3", - "dev": true, "requires": { "color-name": "1.1.3" } }, "color-name": { - "version": "1.1.3", - "dev": true + "version": "1.1.3" }, "colord": { "version": "2.9.2", @@ -18604,8 +18663,7 @@ "dev": true }, "cssesc": { - "version": "3.0.0", - "dev": true + "version": "3.0.0" }, "cssnano": { "version": "5.1.7", @@ -18682,6 +18740,11 @@ "csstype": { "version": "2.6.20" }, + "custom-event-polyfill": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz", + "integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==" + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -18817,8 +18880,7 @@ } }, "defined": { - "version": "1.0.0", - "dev": true + "version": "1.0.0" }, "delayed-stream": { "version": "1.0.0", @@ -18832,6 +18894,14 @@ "version": "1.0.4", "dev": true }, + "detect-autofill": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/detect-autofill/-/detect-autofill-1.1.4.tgz", + "integrity": "sha512-utCBQwCR/beSnADQmBC7C4tTueBBkYCl6WSpfGUkYKO/+MzPxqYGj6G4MvHzcKmH1gCTK+VunX2vaagvkRXPvA==", + "requires": { + "custom-event-polyfill": "^1.0.7" + } + }, "detect-newline": { "version": "3.1.0", "dev": true @@ -18842,7 +18912,6 @@ }, "detective": { "version": "5.2.0", - "dev": true, "requires": { "acorn-node": "^1.6.1", "defined": "^1.0.0", @@ -18850,8 +18919,7 @@ } }, "didyoumean": { - "version": "1.2.2", - "dev": true + "version": "1.2.2" }, "diff-sequences": { "version": "27.5.1", @@ -18865,8 +18933,7 @@ } }, "dlv": { - "version": "1.1.3", - "dev": true + "version": "1.1.3" }, "dns-equal": { "version": "1.0.0", @@ -19596,7 +19663,6 @@ }, "fast-glob": { "version": "3.2.11", - "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -19607,7 +19673,6 @@ "dependencies": { "glob-parent": { "version": "5.1.2", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -19624,7 +19689,6 @@ }, "fastq": { "version": "1.13.0", - "dev": true, "requires": { "reusify": "^1.0.4" } @@ -19658,7 +19722,6 @@ }, "fill-range": { "version": "7.0.1", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -19761,8 +19824,7 @@ "dev": true }, "function-bind": { - "version": "1.1.1", - "dev": true + "version": "1.1.1" }, "functional-red-black-tree": { "version": "1.0.1", @@ -19810,7 +19872,6 @@ }, "glob-parent": { "version": "6.0.2", - "dev": true, "requires": { "is-glob": "^4.0.3" } @@ -19852,7 +19913,6 @@ }, "has": { "version": "1.0.3", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -20103,7 +20163,6 @@ }, "is-binary-path": { "version": "2.1.0", - "dev": true, "requires": { "binary-extensions": "^2.0.0" } @@ -20127,7 +20186,6 @@ }, "is-core-module": { "version": "2.9.0", - "dev": true, "requires": { "has": "^1.0.3" } @@ -20141,8 +20199,7 @@ "dev": true }, "is-extglob": { - "version": "2.1.1", - "dev": true + "version": "2.1.1" }, "is-file-esm": { "version": "1.0.0", @@ -20161,7 +20218,6 @@ }, "is-glob": { "version": "4.0.3", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -20171,8 +20227,7 @@ "dev": true }, "is-number": { - "version": "7.0.0", - "dev": true + "version": "7.0.0" }, "is-plain-obj": { "version": "3.0.0", @@ -21667,8 +21722,7 @@ } }, "lilconfig": { - "version": "2.0.5", - "dev": true + "version": "2.0.5" }, "lines-and-columns": { "version": "1.2.4", @@ -21929,8 +21983,7 @@ "dev": true }, "merge2": { - "version": "1.4.1", - "dev": true + "version": "1.4.1" }, "methods": { "version": "1.1.2", @@ -21938,7 +21991,6 @@ }, "micromatch": { "version": "4.0.5", - "dev": true, "requires": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -22015,8 +22067,7 @@ } }, "minimist": { - "version": "1.2.6", - "dev": true + "version": "1.2.6" }, "minipass": { "version": "3.1.6", @@ -22036,6 +22087,11 @@ "version": "2.2.2", "dev": true }, + "moment": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" + }, "mrmime": { "version": "1.0.0", "dev": true @@ -22165,8 +22221,7 @@ } }, "normalize-path": { - "version": "3.0.0", - "dev": true + "version": "3.0.0" }, "normalize-range": { "version": "0.1.2", @@ -22199,8 +22254,7 @@ "dev": true }, "object-hash": { - "version": "3.0.0", - "dev": true + "version": "3.0.0" }, "object-keys": { "version": "1.1.1", @@ -22429,8 +22483,7 @@ "dev": true }, "path-parse": { - "version": "1.0.7", - "dev": true + "version": "1.0.7" }, "path-to-regexp": { "version": "0.1.7", @@ -22440,12 +22493,16 @@ "version": "4.0.0", "dev": true }, + "perfect-scrollbar": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz", + "integrity": "sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g==" + }, "picocolors": { "version": "1.0.0" }, "picomatch": { - "version": "2.3.1", - "dev": true + "version": "2.3.1" }, "pirates": { "version": "4.0.5", @@ -22458,6 +22515,11 @@ "find-up": "^4.0.0" } }, + "popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" + }, "portfinder": { "version": "1.0.28", "dev": true, @@ -22531,14 +22593,12 @@ }, "postcss-js": { "version": "4.0.0", - "dev": true, "requires": { "camelcase-css": "^2.0.1" } }, "postcss-load-config": { "version": "3.1.4", - "dev": true, "requires": { "lilconfig": "^2.0.5", "yaml": "^1.10.2" @@ -22642,7 +22702,6 @@ }, "postcss-nested": { "version": "5.0.6", - "dev": true, "requires": { "postcss-selector-parser": "^6.0.6" } @@ -22735,7 +22794,6 @@ }, "postcss-selector-parser": { "version": "6.0.10", - "dev": true, "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -22757,8 +22815,7 @@ } }, "postcss-value-parser": { - "version": "4.2.0", - "dev": true + "version": "4.2.0" }, "prelude-ls": { "version": "1.1.2", @@ -22880,12 +22937,10 @@ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, "queue-microtask": { - "version": "1.2.3", - "dev": true + "version": "1.2.3" }, "quick-lru": { - "version": "5.1.1", - "dev": true + "version": "5.1.1" }, "randombytes": { "version": "2.1.0", @@ -22960,7 +23015,6 @@ }, "readdirp": { "version": "3.6.0", - "dev": true, "requires": { "picomatch": "^2.2.1" } @@ -23048,7 +23102,6 @@ }, "resolve": { "version": "1.22.0", - "dev": true, "requires": { "is-core-module": "^2.8.1", "path-parse": "^1.0.7", @@ -23087,8 +23140,7 @@ "dev": true }, "reusify": { - "version": "1.0.4", - "dev": true + "version": "1.0.4" }, "rimraf": { "version": "3.0.2", @@ -23102,7 +23154,6 @@ }, "run-parallel": { "version": "1.2.0", - "dev": true, "requires": { "queue-microtask": "^1.2.2" } @@ -23588,8 +23639,7 @@ } }, "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "dev": true + "version": "1.0.0" }, "svg-tags": { "version": "1.0.0", @@ -23647,7 +23697,6 @@ }, "tailwindcss": { "version": "3.0.24", - "dev": true, "requires": { "arg": "^5.0.1", "chokidar": "^3.5.3", @@ -23673,8 +23722,7 @@ }, "dependencies": { "color-name": { - "version": "1.1.4", - "dev": true + "version": "1.1.4" } } }, @@ -23812,7 +23860,6 @@ }, "to-regex-range": { "version": "5.0.1", - "dev": true, "requires": { "is-number": "^7.0.0" } @@ -23871,6 +23918,21 @@ "version": "2.3.1", "dev": true }, + "tw-elements": { + "version": "1.0.0-alpha12", + "resolved": "https://registry.npmjs.org/tw-elements/-/tw-elements-1.0.0-alpha12.tgz", + "integrity": "sha512-AQHwXIC4kw4T0NPKAi0vD1bkHSiA4RhdXqqnXDWEHKsrN02njc/ITB3YZ92s2f2jt+wBPI2UOpeUsWL5xiMVeQ==", + "requires": { + "@popperjs/core": "^2.6.0", + "chart.js": "^2.9.4", + "chartjs-plugin-datalabels": "^0.7.0", + "deepmerge": "^4.2.2", + "detect-autofill": "^1.1.3", + "perfect-scrollbar": "^1.5.0", + "popper.js": "^1.16.1", + "tailwindcss": "^3.0.7" + } + }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", @@ -23965,8 +24027,7 @@ } }, "util-deprecate": { - "version": "1.0.2", - "dev": true + "version": "1.0.2" }, "utila": { "version": "0.4.0", @@ -24599,8 +24660,7 @@ "dev": true }, "xtend": { - "version": "4.0.2", - "dev": true + "version": "4.0.2" }, "y18n": { "version": "5.0.8", @@ -24617,8 +24677,7 @@ "dev": true }, "yaml": { - "version": "1.10.2", - "dev": true + "version": "1.10.2" }, "yargs": { "version": "16.2.0", diff --git a/package.json b/package.json index 66788b9ffdf616d6288db4223c4c69ed8106e191..4b4f06e87feea6cbf22be72ac5bacc3aed4b4eaf 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "roboto-fontface": "*", "sockjs-client": "^1.6.0", "stompjs": "^2.3.3", + "tw-elements": "^1.0.0-alpha12", "vue": "^3.2.13", "vue-router": "^4.0.3", "vuelidate": "^0.7.7", diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2bbee9c7589aa7943fe472849934b7f220ed43cd Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000000000000000000000000000000000000..41235286563508e0feb4c451a34b598ef822ec21 --- /dev/null +++ b/public/index.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width,initial-scale=1.0"> + <link rel="icon" href="<%= BASE_URL %>favicon.ico"> + <title><%= htmlWebpackPlugin.options.title %></title> + </head> + <body> + <noscript> + <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> + </noscript> + <div id="app"></div> + <!-- built files will be auto injected --> + </body> +</html> diff --git a/src/App.vue b/src/App.vue index 91695eb7395ebb9a45774a95415215684ce798b7..8b981fa82ba0894398770b4837b3acf32161f24b 100644 --- a/src/App.vue +++ b/src/App.vue @@ -9,14 +9,18 @@ import { defineComponent } from "vue"; // Components - -import NavBar from "./components/NavigationComponents/NavBar.vue"; +import NavBar from "./components/BaseComponents/NavBar.vue"; export default defineComponent({ name: "App", - components: { NavBar, }, }); </script> + +<style global> +@tailwind base; +@tailwind components; +@tailwind utilities; +</style> diff --git a/src/components/BaseComponents/CommunityHeader.vue b/src/components/BaseComponents/CommunityHeader.vue index 99fde7e4f3ca32f7931a1f4aed0ed7735ea87e98..6e2b31a722f7401e93c6d9d640ca911b85d1f251 100644 --- a/src/components/BaseComponents/CommunityHeader.vue +++ b/src/components/BaseComponents/CommunityHeader.vue @@ -27,35 +27,49 @@ </div> </div> </div> - <div class="flex"> + <div> <span class="hidden sm:block"> - <button - v-if="adminStatus" - @click="edit()" - type="button" - class="inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" + <!-- Legg dette til i button: v-if="adminStatus" --> + + <svg + @click="toggle" + xmlns="http://www.w3.org/2000/svg" + class="w-9 h-9 cursor-pointer" + fill="none" + viewBox="0 0 24 24" + stroke="currentColor" > - <!-- Heroicon name: solid/pencil --> - <svg - xmlns="http://www.w3.org/2000/svg" - class="h-5 w-5" - viewBox="0 0 20 20" - fill="currentColor" - > - <path - d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" - /> - </svg> - Edit - </button> + <path + stroke-linecap="round" + stroke-linejoin="round" + stroke-width="2" + d="M4 6h16M4 12h16M4 18h16" + /> + </svg> + + <CommunityHamburger + v-if="hamburgerOpen" + class="origin-top-right absolute right-0" + :community-i-d="community.communityId" + /> + <!-- class="absolute" --> </span> </div> </div> </template> <script> +import CommunityHamburger from "@/components/CommunityComponents/CommunityHamburger"; export default { name: "CommunityHeader", + components: { + CommunityHamburger, + }, + data() { + return { + hamburgerOpen: false, + }; + }, props: { adminStatus: Boolean, community: { @@ -68,8 +82,12 @@ export default { }, }, methods: { - edit() { - this.$emit("edit"); + toggle: function () { + if (this.hamburgerOpen) { + this.hamburgerOpen = false; + } else { + this.hamburgerOpen = true; + } }, }, }; diff --git a/src/components/BaseComponents/CustomFooterModal.vue b/src/components/BaseComponents/CustomFooterModal.vue new file mode 100644 index 0000000000000000000000000000000000000000..8a6e57ca1707d02d53ab57a00b3c2626587f146d --- /dev/null +++ b/src/components/BaseComponents/CustomFooterModal.vue @@ -0,0 +1,65 @@ +<template> + <!-- Main modal --> + <div + v-if="visible" + class="fixed grid place-items-center bg-gray-600 bg-opacity-50 top-0 left-0 right-0 z-50 w-full overflow-x-hidden overflow-y-auto md:inset-0 h-modal md:h-full" + > + <div class="relative w-full h-full max-w-2xl p-4 md:h-auto"> + <!-- Modal content --> + <div class="relative bg-white rounded-lg shadow dark:bg-gray-700"> + <!-- Modal header --> + <div + class="flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600" + > + <h3 class="text-xl font-semibold text-gray-900 dark:text-white"> + {{ title }} + </h3> + <button + @click="close()" + class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" + > + <svg + class="w-5 h-5" + fill="currentColor" + viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg" + > + <path + fill-rule="evenodd" + d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" + clip-rule="evenodd" + ></path> + </svg> + </button> + </div> + <!-- Modal body --> + <div class="p-6 space-y-6"> + <p class="text-base leading-relaxed text-gray-500 dark:text-gray-400"> + {{ message }} + </p> + </div> + <!-- Modal footer --> + <div class="rounded-b border-t border-gray-200 dark:border-gray-600"> + <!-- Slot: Add any html you want here --> + <slot /> + </div> + </div> + </div> + </div> +</template> + +<script> +export default { + name: "CustomFooterModal", + props: { + visible: Boolean, + title: String, + message: String, + }, + methods: { + close() { + this.$emit("close"); + }, + }, +}; +</script> diff --git a/src/components/BaseComponents/IconButton.vue b/src/components/BaseComponents/IconButton.vue new file mode 100644 index 0000000000000000000000000000000000000000..4bacbdf64c9f36c6ce5e9bc29146e24737f55ea4 --- /dev/null +++ b/src/components/BaseComponents/IconButton.vue @@ -0,0 +1,30 @@ +<template> + <!-- Icon button --> + <button + class="block w-fit text-white text-base bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" + > + <div class="flex flex-row px-5 py-2.5 h-10"> + <!-- Icon slot: Default content "Ban"-icon --> + <div class="h-6 w-6"> + <slot> + <BanIcon /> + </slot> + </div> + <p>{{ text }}</p> + </div> + </button> +</template> + +<script> +import { BanIcon } from "@heroicons/vue/outline"; + +export default { + name: "IconButton", + props: { + text: String, + }, + components: { + BanIcon, + }, +}; +</script> diff --git a/src/components/NavigationComponents/NavBar.vue b/src/components/BaseComponents/NavBar.vue similarity index 100% rename from src/components/NavigationComponents/NavBar.vue rename to src/components/BaseComponents/NavBar.vue diff --git a/src/components/NavigationComponents/NotificationsForm.vue b/src/components/BaseComponents/NotificationsForm.vue similarity index 100% rename from src/components/NavigationComponents/NotificationsForm.vue rename to src/components/BaseComponents/NotificationsForm.vue diff --git a/src/components/ChatComponents/ChatMessage.vue b/src/components/ChatComponents/ChatMessage.vue index 58720e89792b63889b4de9db9f870e47fc4eeeeb..d3e016a3d4b947d0b90cedb3ea9e07093a47a206 100644 --- a/src/components/ChatComponents/ChatMessage.vue +++ b/src/components/ChatComponents/ChatMessage.vue @@ -47,7 +47,7 @@ export default { calculateTime() { //let time = this.message.from; // Calculate time when message was sent - let date = new Date(Date.now()); + let date = new Date(this.message.timestamp); let hours = date.getHours(); let minutes = "0" + date.getMinutes(); let formattedTime = hours + ":" + minutes.substr(-2); diff --git a/src/components/CommunityComponents/CommunityHamburger.vue b/src/components/CommunityComponents/CommunityHamburger.vue new file mode 100644 index 0000000000000000000000000000000000000000..e060566e73a400fbe368f168136a2e1cff1f8a7b --- /dev/null +++ b/src/components/CommunityComponents/CommunityHamburger.vue @@ -0,0 +1,46 @@ +<template> + <div + id="dropdown" + class="z-10 w-44 text-base list-none bg-white rounded divide-y divide-gray-100 shadow dark:bg-gray-700" + > + <ul class="py-1"> + <li id="newItem"> + <router-link + to="/addNewItem" + class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white" + >Opprett Utleie</router-link + > + </li> + <li id="getMembers"> + <router-link + :to="'/group/' + communityID + '/memberlist'" + class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white" + >Se Medlemmer + </router-link> + </li> + <li id="adminGroup"> + <router-link + :to="'/group/' + communityID + '/memberlist'" + class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white" + >Administrer Gruppe</router-link + > + </li> + <li id="leaveGroup"> + <div + class="cursor-pointer block py-2 px-4 text-sm text-red-600 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white" + > + Forlat Gruppe + </div> + </li> + </ul> + </div> +</template> + +<script> +export default { + name: "CommunityHamburger", + props: { + communityID: Number, + }, +}; +</script> diff --git a/src/components/CommunityComponents/CommunityHome.vue b/src/components/CommunityComponents/CommunityHome.vue index 03c7e4e20b83acb9e09e9ba035022e582498c5ed..e6cf391a30732b1b29ac542848fe4cfac2c58b8c 100644 --- a/src/components/CommunityComponents/CommunityHome.vue +++ b/src/components/CommunityComponents/CommunityHome.vue @@ -34,7 +34,12 @@ <div class="grid grid-flow-row-dense grid-cols-2 md:grid-cols-4 lg:grid-cols-5 w-full place-items-center" > - <ItemCard v-for="item in searchedItems" :key="item" :item="item" /> + <ItemCard + v-for="item in searchedItems" + :key="item" + :item="item" + @click="goToItemInfoPage(item.listingID)" + /> </div> </div> </section> @@ -66,11 +71,16 @@ export default { return filteredItems; }, }, - + created() { + if (this.$store.state.user.token !== null) { + this.isLoggedIn = true; + } + }, data() { return { items: [], item: { + listingID: 0, img: "", address: "", title: "", @@ -92,6 +102,9 @@ export default { .communityID; this.items = await GetListingsInCommunity(this.communityID); }, + goToItemInfoPage(item) { + this.$router.push("/itempage/" + item); + }, }, beforeMount() { this.getCommunityFromAPI(); //To get the id of the community before mounting the view diff --git a/src/components/CommunityComponents/CommunityList.vue b/src/components/CommunityComponents/CommunityList.vue index 045eeadf16730ecd725b4e0c9990fbad0ee3d9ca..859e69d3e7f96c56935f64dd7b16beca2f403188 100644 --- a/src/components/CommunityComponents/CommunityList.vue +++ b/src/components/CommunityComponents/CommunityList.vue @@ -1,21 +1,22 @@ <template> <ul> - <li v-for="(group, index) in groupList" :key="index"> - <group-list-item :group="group" /> + <li v-for="community in communities" :key="community"> + <CommunityListItem :community="community" :member="member" /> </li> </ul> </template> <script> -import GroupListItem from "@/components/CommunityComponents/CommunityListItem.vue"; +import CommunityListItem from "@/components/CommunityComponents/CommunityListItem.vue"; export default { - name: "GroupList", + name: "CommunityList", props: { - groupList: Array, + communities: Array, + member: Boolean, }, components: { - GroupListItem, + CommunityListItem, }, }; </script> diff --git a/src/components/CommunityComponents/CommunityListItem.vue b/src/components/CommunityComponents/CommunityListItem.vue index 81d2b7dee530d7eae79f97e954ff19a52936bd34..d75938f456c1ed61aad0ebc89db8e04a2282bc2f 100644 --- a/src/components/CommunityComponents/CommunityListItem.vue +++ b/src/components/CommunityComponents/CommunityListItem.vue @@ -1,46 +1,66 @@ <template> + <CustomFooterModal + @close="this.dialogOpen = false" + :visible="dialogOpen" + :title="community.name" + :message="community.description" + > + <div class="flex justify-center p-2"> + <ColoredButton + v-if="!member" + :text="'Bli med'" + @click="goToJoin(community.communityId)" + /> + <ColoredButton + v-if="member" + :text="'Gå til'" + @click="goToGroup(community.communityId)" + /> + </div> + </CustomFooterModal> <div + @click="toggleDialog()" class="bg-white shadow dark:bg-gray-800 select-none cursor-pointer hover:bg-gray-50 flex items-center p-4" > <div class="h-10 w-10 flex flex-col justify-center items-center mr-4"> - <img alt="groupIMG" src="../../assets/group.png" /> + <UserGroupIcon v-if="!community.image" alt="Felleskapets bilde" /> + <!-- TODO: USE COMMUNITY IMAGE <img alt="Felleskapets bilde" src="@/assets/group.png" /> --> </div> - <div class="flex-1 pl-1"> - <div class="font-medium dark:text-white"> - {{ group.name }} + <div class="flex-1 pl-1 overflow-hidden"> + <div class="font-medium dark:text-white truncate"> + {{ community.name }} </div> </div> - <div class="flex flex-row justify-center"> - <button - @click="goToJoin(group.communityId)" - v-if="!isMember" - class="px-4 py-2 w-24 font-medium tracking-wide text-white capitalize transition-colors duration-200 transform bg-blue-600 rounded-md hover:bg-blue-500 focus:outline-none focus:ring focus:ring-blue-300 focus:ring-opacity-80" - > - Bli med - </button> - <button - v-if="isMember" - @click="goToGroup(group.communityId)" - class="px-4 py-2 w-24 font-medium tracking-wide text-white capitalize transition-colors duration-200 transform bg-blue-600 rounded-md hover:bg-blue-500 focus:outline-none focus:ring focus:ring-blue-300 focus:ring-opacity-80" - > - Gå til - </button> + <div class="flex flex-row justify-center items-center"> + <LockClosedIcon + v-if="community.visibility === 0" + class="max-h-6 max-w-6 shrink m-2" + /> </div> </div> </template> <script> -import { getMyGroups } from "@/utils/apiutil"; +import CustomFooterModal from "@/components/BaseComponents/CustomFooterModal.vue"; +import ColoredButton from "@/components/BaseComponents/ColoredButton.vue"; +import { UserGroupIcon, LockClosedIcon } from "@heroicons/vue/outline"; export default { - name: "GroupListItem", + name: "CommunityListItem", + components: { + CustomFooterModal, + ColoredButton, + UserGroupIcon, + LockClosedIcon, + }, data() { return { - myGroups: [], + dialogOpen: false, }; }, props: { - group: Object, + community: Object, + member: Boolean, }, methods: { goToGroup(id) { @@ -49,15 +69,9 @@ export default { goToJoin(id) { this.$router.push("/community/" + id + "/join"); }, - async getMyGroups() { - this.myGroups = await getMyGroups(); + toggleDialog() { + this.dialogOpen = !this.dialogOpen; }, - isMember(group) { - return this.myGroups.includes(group); - }, - }, - beforeMount() { - this.getMyGroups(); }, }; </script> diff --git a/src/components/CommunityComponents/MemberList.vue b/src/components/CommunityComponents/MemberList.vue index 7b44f5fa5a3fa3ba4ef464e0400a22613eb6c819..b8360de5851fd26e86d6e9c5925f68eec3011e31 100644 --- a/src/components/CommunityComponents/MemberList.vue +++ b/src/components/CommunityComponents/MemberList.vue @@ -1,4 +1,9 @@ <template> + <CommunityHeader + :admin-status="false" + :community="community" + class="mb-5 mt-5" + /> <ul> <li v-for="member in memberlist" :key="member.userId"> <user-list-item-card :admin="admin" :user="member" /> @@ -8,29 +13,38 @@ <script> import UserListItemCard from "../UserProfileComponents/UserListItemCard.vue"; +import { GetMembersOfCommunity, GetCommunity } from "@/utils/apiutil"; +import CommunityHeader from "@/components/BaseComponents/CommunityHeader"; export default { data() { return { - memberlist: [ - { - userId: 2, - firstName: "erik", - lastName: "hansen", - }, - { - userId: 1, - firstName: "Test", - lastName: "Testesen", - }, - ], + memberlist: [], + community: {}, }; }, components: { + CommunityHeader, UserListItemCard, }, props: { admin: Boolean, }, + methods: { + getAllMembersOfCommunity: async function () { + this.memberlist = await GetMembersOfCommunity( + this.$router.currentRoute.value.params.id + ); + }, + getCommunity: async function () { + this.community = await GetCommunity( + this.$router.currentRoute.value.params.id + ); + }, + }, + beforeMount() { + this.getAllMembersOfCommunity(); + this.getCommunity(); + }, }; </script> diff --git a/src/components/FormComponents/RegisterForm.vue b/src/components/FormComponents/RegisterForm.vue index 240895bffbe2fe98be228f19e2d7549f3bc24227..3f4551a3e677e01b48cfcc29cb889b21d9bf04c1 100644 --- a/src/components/FormComponents/RegisterForm.vue +++ b/src/components/FormComponents/RegisterForm.vue @@ -182,15 +182,15 @@ export default { const loginResponse = await doLogin(loginRequest); - if (loginResponse === "Failed login") { + if (loginResponse.isLoggedIn === false) { this.errorMessage = "Failed to log in with new user"; this.$store.commit("logout"); - this.$router.push("/login"); + await this.$router.push("/login"); return; } - this.$store.commit("saveToken", loginResponse); - this.$router.push("/"); + this.$store.commit("saveToken", loginResponse.token); + await this.$router.push("/"); }, async sendRegisterRequest() { const registerInfo = { diff --git a/src/components/RentingComponents/ImageCarousel.vue b/src/components/RentingComponents/ImageCarousel.vue new file mode 100644 index 0000000000000000000000000000000000000000..aef0e652e6609273c2505025287c152ece3d10d4 --- /dev/null +++ b/src/components/RentingComponents/ImageCarousel.vue @@ -0,0 +1,78 @@ +<template> + <div + id="carouselIndicators" + class="carousel slide relative" + data-bs-ride="carousel" + > + <div + class="carousel-indicators absolute right-0 bottom-0 left-0 flex justify-center p-0 mb-4" + > + <button + v-for="(image, i) in images" + :key="i" + type="button" + data-bs-target="#carouselIndicators" + :data-bs-slide-to="i" + :class="{ active: i === 0 }" + :aria-current="i === 0 ? 'true' : 'false'" + :aria-label="'Slide ' + (i + 1)" + ></button> + </div> + <div class="carousel-inner relative w-full overflow-hidden"> + <div + v-for="(image, i) in images" + :key="i" + :class="'carousel-item float-left w-full' + (i == 0 ? ' active' : '')" + > + <img :src="image.src" class="block w-full" :alt="image.alt" /> + </div> + </div> + <button + class="carousel-control-prev absolute top-0 bottom-0 flex items-center justify-center p-0 text-center border-0 hover:outline-none hover:no-underline focus:outline-none focus:no-underline left-0" + type="button" + data-bs-target="#carouselIndicators" + data-bs-slide="prev" + > + <span + class="carousel-control-prev-icon inline-block bg-no-repeat" + aria-hidden="true" + ></span> + <span class="visually-hidden">Previous</span> + </button> + <button + class="carousel-control-next absolute top-0 bottom-0 flex items-center justify-center p-0 text-center border-0 hover:outline-none hover:no-underline focus:outline-none focus:no-underline right-0" + type="button" + data-bs-target="#carouselIndicators" + data-bs-slide="next" + > + <span + class="carousel-control-next-icon inline-block bg-no-repeat" + aria-hidden="true" + ></span> + <span class="visually-hidden">Next</span> + </button> + </div> +</template> + +<script> +/* +{ + src: "imageURL", + alt: "IMAGE ALT TEXT" +} +*/ +import "tw-elements"; +export default { + props: { + images: { + type: Array, + required: true, + }, + }, + data() { + return {}; + }, +}; +</script> + +<style scoped></style> diff --git a/src/components/RentingComponents/ItemInfo.vue b/src/components/RentingComponents/ItemInfo.vue new file mode 100644 index 0000000000000000000000000000000000000000..61c4e6099a972322c1e05b475af8421e75cb92b1 --- /dev/null +++ b/src/components/RentingComponents/ItemInfo.vue @@ -0,0 +1,142 @@ +<template> + <div> + <div> + <ImageCarousel :images="pictures"></ImageCarousel> + </div> + <!-- Product info --> + <div + class="max-w-2xl mx-auto pt-10 pb-16 px-4 sm:px-6 lg:max-w-7xl lg:pt-16 lg:pb-24 lg:px-8 lg:grid lg:grid-cols-3 lg:grid-rows-[auto,auto,1fr] lg:gap-x-8" + > + <div class="lg:col-span-2 lg:border-r lg:border-gray-200 lg:pr-8"> + <h1 + class="text-2xl font-extrabold tracking-tight text-gray-900 sm:text-3xl" + > + {{ item.title }} + </h1> + </div> + <div + class="py-10 lg:pt-6 lg:pb-16 lg:col-start-1 lg:col-span-2 lg:border-r lg:border-gray-200 lg:pr-8" + > + <!-- Description and details --> + <div> + <h3 class="text-base font-semibold text-gray-900">Pris per dag</h3> + + <div class="space-y-6"> + <p class="text-2xl font-medium text-gray-900"> + {{ item.pricePerDay }} kr + </p> + </div> + </div> + <div class="mt-4"> + <h3 class="text-base font-base text-gray-900">Ledige tidspunkter</h3> + + <div> + <p class="text-sm text-gray-900"> + (placeholder skal byttes ut med date-picker) + </p> + </div> + </div> + <div class="mt-10"> + <div class="mt-4 space-y-6"> + <p class="text-sm text-gray-600">{{ item.description }}</p> + </div> + </div> + <div class="mt-6"> + <!-- Add in method for displaying user card. Use item.userID on the method --> + (Placeholder) Add usercard here + <UserListItemCard :admin="false" :user="this.item.userID"></UserListItemCard> + </div> + <div> + <div class="mt-4 space-y-6"> + <p class="text-base font-semibold text-gray-900"> + {{ item.address }} + </p> + </div> + </div> + <div class="mt-10"> + <h3 class="text-base font-semibold text-gray-900">Totalprisen er</h3> + + <div class="mt-2 space-y-2"> + <p class="text-xl font-medium text-gray-900"> + mye (Change with tot price from calc method) + </p> + <button> + <!-- This button should send you to the rent page --> + Rent page + </button> + </div> + </div> + </div> + </div> + </div> +</template> + +<script> +import { getItem } from "@/utils/apiutil"; +import { getItemPictures } from "@/utils/apiutil"; +import ImageCarousel from "@/components/RentingComponents/ImageCarousel.vue"; +import UserListItemCard from "@/components/UserProfileComponents/UserListItemCard.vue"; + +export default { + name: "ItemInfo", + data() { + return { + item: { + listingID: 0, + title: "", + description: "", + pricePerDay: 0, + address: "", + userID: 0, + categoryNames: [], + communityIDs: [], + }, + images: [ + { + listingID: 0, + picture: "", + }, + ], + pictures: [], + }; + }, + components: { + ImageCarousel, + UserListItemCard, + }, + methods: { + async getItem() { + let id = this.$router.currentRoute.value.params.id; + this.item = await getItem(id); + }, + async getItemPictures() { + let id = this.$router.currentRoute.value.params.id; + this.images = await getItemPictures(id); + + if(this.images.length < 1) { + let noImage = { + src: require('@/assets/default-product.png'), + alt: "No image found", + }; + this.pictures.push(noImage); + } else { + for (let i = 0; i < this.images.length; i++) { + let oneImage = { + src: this.images[i].picture, + //How do i make this accurate to the image? + alt: "An image", + }; + this.pictures.push(oneImage); + } + } + //TODO fixs so each image get a correct alt text. + }, + }, + async beforeMount() { + await this.getItemPictures(); + this.getItem(); + }, +}; +</script> + +<style></style> diff --git a/src/index.css b/src/index.css deleted file mode 100644 index bd6213e1dfe6b0a79ce7d8b37d0d2dc70f0250bb..0000000000000000000000000000000000000000 --- a/src/index.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; \ No newline at end of file diff --git a/src/main.js b/src/main.js index da2685dca10f402e327223ae32fee373b9a0c8c1..32764da4a55678ff6ed1fbf6e21819a55990f716 100644 --- a/src/main.js +++ b/src/main.js @@ -2,7 +2,6 @@ import { createApp } from "vue"; import App from "./App.vue"; import router from "./router"; import store from "./store"; -import "./index.css"; import ws from "./services/ws"; createApp(App).use(router).use(store).mount("#app"); diff --git a/src/router/index.js b/src/router/index.js index 8ebffcf37a30395bb41d93d15c134d13df004cf5..f1b5c560024d0a7d33cde1c0cc635bc65883b175 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -84,7 +84,8 @@ const routes = [ { path: "/notifications", name: "notifications", - component: () => import("../views/NavigationViews/NotificationView.vue"), + component: () => + import("../components/BaseComponents/NotificationsForm.vue"), beforeEnter: guardRoute, }, { @@ -101,7 +102,17 @@ const routes = [ path: "/newRent", name: "newRent", component: () => import("../views/RentingViews/NewRentView.vue"), + }, + { beforeEnter: guardRoute, + path: "/test", + name: "test", + component: () => import("../views/TestView.vue"), + }, + { + path: "/itempage/:id", + name: "ItemInfo", + component: () => import("../views/RentingViews/ItemInfoPageView.vue"), }, ]; diff --git a/src/utils/apiutil.js b/src/utils/apiutil.js index 1f1fd53fcdbed879e708809aa5eb99b14f4882e7..76c8d4b45c63e214d7b97e0bacf74824634d413b 100644 --- a/src/utils/apiutil.js +++ b/src/utils/apiutil.js @@ -162,6 +162,33 @@ export function getVisibleGroups() { }); } +export function getItem(itemid) { + return axios + .get(API_URL + "listing/" + itemid, { + headers: tokenHeader(), + }) + .then((response) => { + return response.data; + }) + .catch((error) => { + console.error(error); + }); +} + +export async function getItemPictures(itemid) { + let res = await axios + .get(API_URL + "listing/" + itemid + "/pictures", { + headers: tokenHeader(), + }) + .then((response) => { + return response.data; + }) + .catch((error) => { + console.error(error); + }); + return res; +} + export async function GetCommunity(communityID) { return axios .get(API_URL + "community/" + communityID, { @@ -187,3 +214,16 @@ export async function GetListingsInCommunity(communityID) { console.error(error); }); } + +export async function GetMembersOfCommunity(communityID) { + return axios + .get(API_URL + "community/" + communityID + "/members", { + headers: tokenHeader(), + }) + .then((response) => { + return response.data; + }) + .catch((error) => { + console.error(error); + }); +} diff --git a/src/views/CommunityViews/CommunityHomeView.vue b/src/views/CommunityViews/CommunityHomeView.vue index cabfd1b6ed2ea1e5775868f160484ddd9fa99b06..40886b3feb0816f305ee4a5045f180478677c8bb 100644 --- a/src/views/CommunityViews/CommunityHomeView.vue +++ b/src/views/CommunityViews/CommunityHomeView.vue @@ -1,15 +1,13 @@ <template> - <GroupHome></GroupHome> + <CommunityHome /> </template> <script> -import GroupHome from "@/components/CommunityComponents/CommunityHome"; +import CommunityHome from "@/components/CommunityComponents/CommunityHome.vue"; export default { - name: "GroupHomeView.vue", + name: "CommunityHomeView", components: { - GroupHome, + CommunityHome, }, }; </script> - -<style scoped></style> diff --git a/src/views/CommunityViews/CommunityView.vue b/src/views/CommunityViews/CommunityView.vue index 08d8116dbc21d5b624d2526ff7528b614c7dd43c..9fd39f5f305a7592f633795254899fa3cf3883a8 100644 --- a/src/views/CommunityViews/CommunityView.vue +++ b/src/views/CommunityViews/CommunityView.vue @@ -1,55 +1,49 @@ <template> - <div> - <img - class="cursor-pointer h-8 mr-4 mt-4 float-right" - v-if="isLoggedIn" - src="@/assets/newCommunity.png" - alt="Legg til gruppe" - @click="$router.push('/createNewGroup')" - /> - </div> - <div> - <div id="myGroups" v-if="isLoggedIn"> - <div class="m-4">Mine grupper:</div> - <group-list :groupList="myGroups" /> - </div> - <div id="localGroups"> - <div class="m-4">Offentlige grupper:</div> - <group-list :groupList="localGroups" /> + <div v-if="loggedIn"> + <div class="flex flex-row p-4 relative"> + <p class="capitalize font-bold w-full">Mine felleskap</p> + <PlusIcon + class="cursor-pointer max-h-6 max-w-6 float-right grow" + @click="$router.push('/createNewGroup')" + v-if="loggedIn" + alt="Lag ett nytt felleskap" + /> </div> + <CommunityList :communities="myCommunities" :member="true" /> </div> + <p class="capitalize font-bold w-full p-4">Offentlige felleskap</p> + <CommunityList :communities="publicCommunities" :member="false" /> </template> <script> -import GroupList from "@/components/CommunityComponents/CommunityList.vue"; +import CommunityList from "@/components/CommunityComponents/CommunityList.vue"; import { getMyGroups, getVisibleGroups } from "@/utils/apiutil"; +import { PlusIcon } from "@heroicons/vue/outline"; export default { name: "HomeView", data() { return { - isLoggedIn: false, - myGroups: [], - localGroups: [], + loggedIn: false, + myCommunities: [], + publicCommunities: [], }; }, components: { - GroupList, - }, - methods: { - async getMyGroups() { - this.myGroups = await getMyGroups(); - }, - async getPotentialGroups() { - this.localGroups = await getVisibleGroups(); - }, + CommunityList, + PlusIcon, }, async created() { - await this.getMyGroups(); - await this.getPotentialGroups(); - if (this.$store.state.user.token !== null) { - this.isLoggedIn = true; - } + this.publicCommunities = await getVisibleGroups(); + this.loggedIn = this.$store.state.user.token !== null; + if (!this.loggedIn) return; + + this.myCommunities = await getMyGroups(); + + // Remove all of the user's communities from the public communities arrays + this.publicCommunities = this.publicCommunities.filter( + (val) => !this.myCommunities.includes(val) + ); }, }; </script> diff --git a/src/views/CommunityViews/MemberListView.vue b/src/views/CommunityViews/MemberListView.vue index d250c0d86d6909e6813594be74e75f2616f29fec..9f63b476d52810f37e88b726803ca54b6ccc9266 100644 --- a/src/views/CommunityViews/MemberListView.vue +++ b/src/views/CommunityViews/MemberListView.vue @@ -1,83 +1,13 @@ <template> - <div class="flex items-center justify-between mx-4"> - <div class="flex-1 min-w-0"> - <h2 - class="text-2xl font-bold leading-7 text-gray-900 sm:text-3xl sm:truncate" - > - {{ groupe.name }} - </h2> - <div - class="mt-1 flex flex-col sm:flex-row sm:flex-wrap sm:mt-0 sm:space-x-6" - > - <div class="mt-2 flex items-center text-sm text-gray-500"> - <svg - class="flex-shrink-0 mr-1.5 h-5 w-5 text-gray-400" - xmlns="http://www.w3.org/2000/svg" - viewBox="0 0 20 20" - fill="currentColor" - aria-hidden="true" - > - <path - fill-rule="evenodd" - d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" - clip-rule="evenodd" - /> - </svg> - {{ groupe.address }} - </div> - </div> - </div> - <div class="flex"> - <span class="hidden sm:block"> - <button - v-if="adminStatus" - @click="edit()" - type="button" - class="inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" - > - <!-- Heroicon name: solid/pencil --> - <svg - class="-ml-1 mr-2 h-5 w-5 text-gray-500" - xmlns="http://www.w3.org/2000/svg" - viewBox="0 0 20 20" - fill="currentColor" - aria-hidden="true" - > - <path - d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" - /> - </svg> - Edit - </button> - </span> - </div> - </div> - <div class="h-screen bg-gray-200 content-top grid place-items-top"> - <member-list :admin="editing" /> - </div> + <MemberList /> </template> <script> import MemberList from "@/components/CommunityComponents/MemberList.vue"; export default { - data() { - return { - groupe: { - name: "Solsikken borettslag", - address: "Sollia 6, 7033 Trondheim", - }, - adminStatus: false, - editing: false, - }; - }, components: { MemberList, }, - methods: { - edit() { - this.editing = !this.editing; - }, - }, }; </script> diff --git a/src/views/NavigationViews/NavBarView.vue b/src/views/NavigationViews/NavBarView.vue deleted file mode 100644 index c15762550bcfa1763085a8adca42ac5f39dd4983..0000000000000000000000000000000000000000 --- a/src/views/NavigationViews/NavBarView.vue +++ /dev/null @@ -1,17 +0,0 @@ -<template> - <div> - <Navbar /> - </div> -</template> - -<script> -import Navbar from "@/components/NavigationComponents/NavBar"; -export default { - name: "NavBarView", - components: { - Navbar, - }, -}; -</script> - -<style scoped></style> diff --git a/src/views/NavigationViews/NotificationView.vue b/src/views/NavigationViews/NotificationView.vue deleted file mode 100644 index 91eda3ca2fcf81963a368d41e3a9f466c4ba48da..0000000000000000000000000000000000000000 --- a/src/views/NavigationViews/NotificationView.vue +++ /dev/null @@ -1,18 +0,0 @@ -<template> - <div> - <NotificationsForm /> - </div> -</template> - -<script> -import NotificationsForm from "@/components/NavigationComponents/NotificationsForm"; - -export default { - name: "NotificationView.vue", - components: { - NotificationsForm, - }, -}; -</script> - -<style scoped></style> diff --git a/src/views/RentingViews/ItemInfoPageView.vue b/src/views/RentingViews/ItemInfoPageView.vue new file mode 100644 index 0000000000000000000000000000000000000000..c08362fb9094c59ca4b1419893314bc609648c38 --- /dev/null +++ b/src/views/RentingViews/ItemInfoPageView.vue @@ -0,0 +1,15 @@ +<template> + <ItemInfo></ItemInfo> +</template> + +<script> +import ItemInfo from "@/components/RentingComponents/ItemInfo"; +export default { + name: "ItemInfoPage.vue", + components: { + ItemInfo, + }, +}; +</script> + +<style scoped></style> diff --git a/src/views/TestView.vue b/src/views/TestView.vue new file mode 100644 index 0000000000000000000000000000000000000000..7537e2d18769293327ccda2e2357aefe9973c58e --- /dev/null +++ b/src/views/TestView.vue @@ -0,0 +1,19 @@ +<template> + <div /> +</template> + +<script> +export default { + data() { + return { + show: false, + }; + }, + components: {}, + methods: { + toggleModal() { + this.show = !this.show; + }, + }, +}; +</script> diff --git a/tailwind.config.js b/tailwind.config.js index 7cd4f37efd95627b8f362e1b210fd12b384925d9..d92b980ab15ed8d8de1d9e631b62ea2085bd8705 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,8 +1,12 @@ module.exports = { darkMode: "class", - content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"], + content: [ + "./index.html", + "./src/**/*.{vue,js,ts,jsx,tsx}", + "./node_modules/tw-elements/dist/js/**/*.js", + ], theme: { extend: {}, }, - plugins: [], + plugins: [require("tw-elements/dist/plugin")], }; diff --git a/tests/unit/api-mock-tests/apiutil-communityHome-mock.spec.js b/tests/unit/api-mock-tests/apiutil-communityHome-mock.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..4ab75d6469cf79e31546054eebae45ce5976284d --- /dev/null +++ b/tests/unit/api-mock-tests/apiutil-communityHome-mock.spec.js @@ -0,0 +1,55 @@ +import { GetCommunity, GetListingsInCommunity } from "@/utils/apiutil"; +import axios from "axios"; + +jest.mock("axios"); + +describe("testing mocking of apiutil.js", () => { + it("check that existing group returns correctly", async () => { + const expectedResponse = { + communityId: 4040, + name: "Fisken i vannet", + description: "For vi som liker fjell fisk", + visibility: 1, + location: "Bergen brygge", + picture: "fish blub blub", + }; + + axios.get.mockImplementation(() => + Promise.resolve({ data: expectedResponse }) + ); + + const communityResponse = await GetCommunity(4040); + expect(communityResponse.name).toBe(expectedResponse.name); + }); + + it("check that existing group returns correct listings", async () => { + const expectedResponse = { + item1: { + title: "Fiskekurs", + description: "Fisking og sånn", + pricePerDay: 200, + address: "Vannet", + userID: 6, + categoryNames: null, + communityIDs: null, + }, + + item2: { + title: "TestFraFrontend", + description: "oslo", + pricePerDay: 500, + address: "oslo", + userID: 1, + categoryNames: null, + communityIDs: null, + }, + }; + + axios.get.mockImplementation(() => + Promise.resolve({ data: expectedResponse }) + ); + + const communityItemResponse = await GetListingsInCommunity(4040); + expect(communityItemResponse).toBe(expectedResponse); + }); +}); diff --git a/tests/unit/apiutil-login-mock.spec.js b/tests/unit/api-mock-tests/apiutil-login-mock.spec.js similarity index 100% rename from tests/unit/apiutil-login-mock.spec.js rename to tests/unit/api-mock-tests/apiutil-login-mock.spec.js diff --git a/tests/unit/api-mock-tests/apiutil-memberlist.spec.js b/tests/unit/api-mock-tests/apiutil-memberlist.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..34fb55066190781d9d2aead4d106b2c6ea3c8098 --- /dev/null +++ b/tests/unit/api-mock-tests/apiutil-memberlist.spec.js @@ -0,0 +1,35 @@ +import { GetMembersOfCommunity } from "@/utils/apiutil"; +import axios from "axios"; + +jest.mock("axios"); + +describe("testing mocking of apiutil.js", () => { + it("check that existing group returns correct members", async () => { + const expectedResponse = { + member1: { + userId: 2, + email: "erik@erik.com", + firstName: "erik", + lastName: "hansen", + address: "gløshaugen", + picture: "ok", + }, + + member2: { + userId: 1, + email: "test@test.com", + firstName: "test", + lastName: "testesen", + address: "oslo", + picture: "ok", + }, + }; + + axios.get.mockImplementation(() => + Promise.resolve({ data: expectedResponse }) + ); + + const communityMembersResponse = await GetMembersOfCommunity(4040); + expect(communityMembersResponse).toBe(expectedResponse); + }); +}); diff --git a/tests/unit/apiutil-user-mock.spec.js b/tests/unit/api-mock-tests/apiutil-user-mock.spec.js similarity index 100% rename from tests/unit/apiutil-user-mock.spec.js rename to tests/unit/api-mock-tests/apiutil-user-mock.spec.js diff --git a/tests/unit/component-tests/base-component-tests/__snapshots__/color-button.spec.js.snap b/tests/unit/component-tests/base-component-tests/__snapshots__/color-button.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..4a8d6370547ec8f2d5faee8131dc1432a0d3a7e5 --- /dev/null +++ b/tests/unit/component-tests/base-component-tests/__snapshots__/color-button.spec.js.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ColoredButtonComponent renders correctly 1`] = ` +<button + class="block text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" +> + hei +</button> +`; diff --git a/tests/unit/component-tests/base-component-tests/__snapshots__/community-header.spec.js.snap b/tests/unit/component-tests/base-component-tests/__snapshots__/community-header.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..73847104b73bc72ff7ee7c2c3693159fe201b6b1 --- /dev/null +++ b/tests/unit/component-tests/base-component-tests/__snapshots__/community-header.spec.js.snap @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CommunityHeader component renders correctly 1`] = ` +<div + class="flex items-center justify-between mx-4" +> + <div + class="flex-1 min-w-0" + > + <h2 + class="text-2xl font-bold leading-7 text-gray-900 sm:text-3xl sm:truncate" + > + String + </h2> + <div + class="mt-1 flex flex-col sm:flex-row sm:flex-wrap sm:mt-0 sm:space-x-6" + > + <div + class="mt-2 flex items-center text-sm text-gray-500" + > + <svg + aria-hidden="true" + class="flex-shrink-0 mr-1.5 h-5 w-5 text-gray-400" + fill="currentColor" + viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg" + > + <path + clip-rule="evenodd" + d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" + fill-rule="evenodd" + /> + </svg> + String + </div> + </div> + </div> + <div> + <span + class="hidden sm:block" + > + <!-- Legg dette til i button: v-if="adminStatus" --> + <svg + class="w-9 h-9 cursor-pointer" + fill="none" + stroke="currentColor" + viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M4 6h16M4 12h16M4 18h16" + stroke-linecap="round" + stroke-linejoin="round" + stroke-width="2" + /> + </svg> + <!--v-if--> + <!-- class="absolute" --> + </span> + </div> +</div> +`; diff --git a/tests/unit/component-tests/base-component-tests/__snapshots__/custom-footer-modal.spec.js.snap b/tests/unit/component-tests/base-component-tests/__snapshots__/custom-footer-modal.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..f178175b1fa2913054cc18585b8dd831f1099858 --- /dev/null +++ b/tests/unit/component-tests/base-component-tests/__snapshots__/custom-footer-modal.spec.js.snap @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`IconButtonComponent renders correctly 1`] = ` +<div + data-v-app="" +> + + <!-- Main modal --> + <div + class="fixed grid place-items-center bg-gray-600 bg-opacity-50 top-0 left-0 right-0 z-50 w-full overflow-x-hidden overflow-y-auto md:inset-0 h-modal md:h-full" + > + <div + class="relative w-full h-full max-w-2xl p-4 md:h-auto" + > + <!-- Modal content --> + <div + class="relative bg-white rounded-lg shadow dark:bg-gray-700" + > + <!-- Modal header --> + <div + class="flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600" + > + <h3 + class="text-xl font-semibold text-gray-900 dark:text-white" + > + String + </h3> + <button + class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" + > + <svg + class="w-5 h-5" + fill="currentColor" + viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg" + > + <path + clip-rule="evenodd" + d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" + fill-rule="evenodd" + /> + </svg> + </button> + </div> + <!-- Modal body --> + <div + class="p-6 space-y-6" + > + <p + class="text-base leading-relaxed text-gray-500 dark:text-gray-400" + > + String + </p> + </div> + <!-- Modal footer --> + <div + class="rounded-b border-t border-gray-200 dark:border-gray-600" + > + <!-- Slot: Add any html you want here --> + + <div + class="fake-msg" + > + String + </div> + + </div> + </div> + </div> + </div> + +</div> +`; diff --git a/tests/unit/component-tests/base-component-tests/__snapshots__/icon-button.spec.js.snap b/tests/unit/component-tests/base-component-tests/__snapshots__/icon-button.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..62007d4ff8d81f1ece9bf91271163ca179d7383d --- /dev/null +++ b/tests/unit/component-tests/base-component-tests/__snapshots__/icon-button.spec.js.snap @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`IconButtonComponent renders correctly 1`] = ` +<div + data-v-app="" +> + + <!-- Icon button --> + <button + class="block w-fit text-white text-base bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" + > + <div + class="flex flex-row px-5 py-2.5 h-10" + > + <!-- Icon slot: Default content "Ban"-icon --> + <div + class="h-6 w-6" + > + + <svg + aria-hidden="true" + fill="none" + stroke="currentColor" + stroke-width="2" + viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636" + stroke-linecap="round" + stroke-linejoin="round" + /> + </svg> + + </div> + <p> + hei + </p> + </div> + </button> + +</div> +`; diff --git a/tests/unit/component-tests/base-component-tests/__snapshots__/nav-bar.spec.js.snap b/tests/unit/component-tests/base-component-tests/__snapshots__/nav-bar.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..3929918739cf7ffa3409de46e8c6bd3b6abd14f8 --- /dev/null +++ b/tests/unit/component-tests/base-component-tests/__snapshots__/nav-bar.spec.js.snap @@ -0,0 +1,42 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NavBar component renders correctly 1`] = ` +<nav + class="flex items-center justify-between bg-white h-14 border-1 border-b border-gray-300 border-solid sticky top-0 z-50" +> + <div + class="logo" + > + <img + alt="BoCo logo" + class="m-1 ml-4 cursor-pointer h-12" + src="" + /> + </div> + <ul + class="flex" + > + <li> + <img + alt="Legg til" + class="m-6 cursor-pointer h-7" + src="" + /> + </li> + <li> + <img + alt="Meldinger" + class="m-6 cursor-pointer h-7" + src="" + /> + </li> + <li> + <img + alt="Profil" + class="m-6 cursor-pointer h-7" + src="" + /> + </li> + </ul> +</nav> +`; diff --git a/tests/unit/component-tests/base-component-tests/__snapshots__/notification-modal.spec.js.snap b/tests/unit/component-tests/base-component-tests/__snapshots__/notification-modal.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..6c2259b3f623090effe8ff37ced149d9e72da832 --- /dev/null +++ b/tests/unit/component-tests/base-component-tests/__snapshots__/notification-modal.spec.js.snap @@ -0,0 +1,60 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NotificationModal component renders correctly 1`] = ` +<div + data-v-app="" +> + + <!-- Main modal --> + <div + class="fixed grid place-items-center bg-gray-600 bg-opacity-50 top-0 left-0 right-0 z-50 w-full overflow-x-hidden overflow-y-auto md:inset-0 h-modal md:h-full" + > + <div + class="relative w-full h-full max-w-2xl p-4 md:h-auto" + > + <!-- Modal content --> + <div + class="relative bg-white rounded-lg shadow dark:bg-gray-700" + > + <!-- Modal header --> + <div + class="flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600" + > + <h3 + class="text-xl font-semibold text-gray-900 dark:text-white" + > + String + </h3> + <button + class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" + > + <svg + class="w-5 h-5" + fill="currentColor" + viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg" + > + <path + clip-rule="evenodd" + d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" + fill-rule="evenodd" + /> + </svg> + </button> + </div> + <!-- Modal body --> + <div + class="p-6 space-y-6" + > + <p + class="text-base leading-relaxed text-gray-500 dark:text-gray-400" + > + String + </p> + </div> + </div> + </div> + </div> + +</div> +`; diff --git a/tests/unit/component-tests/base-component-tests/color-button.spec.js b/tests/unit/component-tests/base-component-tests/color-button.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..ca9efb412b59485756b500dcbe8fb283e2464d31 --- /dev/null +++ b/tests/unit/component-tests/base-component-tests/color-button.spec.js @@ -0,0 +1,23 @@ +import { mount } from "@vue/test-utils"; +import ColoredButton from "@/components/BaseComponents/ColoredButton.vue"; + +describe("ColoredButtonComponent", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(ColoredButton, { + //passing prop to component + props: { + text: "hei", + }, + }); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/component-tests/base-component-tests/community-header.spec.js b/tests/unit/component-tests/base-component-tests/community-header.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..7dd3c446f57353aae804f8b7f6cf6e95fe5af7da --- /dev/null +++ b/tests/unit/component-tests/base-component-tests/community-header.spec.js @@ -0,0 +1,31 @@ +import { mount } from "@vue/test-utils"; +import CommunityHeader from "@/components/BaseComponents/CommunityHeader.vue"; + +describe("CommunityHeader component", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(CommunityHeader, { + //passing prop to component + props: { + adminStatus: true, + community: { + communityId: 1, + name: "String", + description: "String", + visibility: 0, + location: "String", + picture: "String", + }, + }, + }); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/component-tests/base-component-tests/custom-footer-modal.spec.js b/tests/unit/component-tests/base-component-tests/custom-footer-modal.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..4d4db9169c1d7c90402aa4e78be331938ebf487f --- /dev/null +++ b/tests/unit/component-tests/base-component-tests/custom-footer-modal.spec.js @@ -0,0 +1,28 @@ +import { mount } from "@vue/test-utils"; +import CustomFooterModal from "@/components/BaseComponents/CustomFooterModal.vue"; + +describe("IconButtonComponent", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(CustomFooterModal, { + //passing prop to component + props: { + visible: true, + title: "String", + message: "String", + }, + slots: { + default: '<div class="fake-msg">String</div>', + }, + }); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/component-tests/base-component-tests/icon-button.spec.js b/tests/unit/component-tests/base-component-tests/icon-button.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..57b6f0fbc8450074c308627cd845f61085cb6743 --- /dev/null +++ b/tests/unit/component-tests/base-component-tests/icon-button.spec.js @@ -0,0 +1,23 @@ +import { mount } from "@vue/test-utils"; +import IconButton from "@/components/BaseComponents/IconButton.vue"; + +describe("IconButtonComponent", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(IconButton, { + //passing prop to component + props: { + text: "hei", + }, + }); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/component-tests/base-component-tests/nav-bar.spec.js b/tests/unit/component-tests/base-component-tests/nav-bar.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..dd5f979fef779d7b5235c2853b8c0b938f184b46 --- /dev/null +++ b/tests/unit/component-tests/base-component-tests/nav-bar.spec.js @@ -0,0 +1,18 @@ +import { mount } from "@vue/test-utils"; +import NavBar from "@/components/BaseComponents/NavBar.vue"; + +describe("NavBar component", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(NavBar); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/component-tests/base-component-tests/notification-modal.spec.js b/tests/unit/component-tests/base-component-tests/notification-modal.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..0fb2c913ba0efa291df6a397a8dd0ee7370da776 --- /dev/null +++ b/tests/unit/component-tests/base-component-tests/notification-modal.spec.js @@ -0,0 +1,25 @@ +import { mount } from "@vue/test-utils"; +import NotificationModal from "@/components/BaseComponents/NotificationModal.vue"; + +describe("NotificationModal component", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(NotificationModal, { + //passing prop to component + props: { + visible: true, + title: "String", + message: "String", + }, + }); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/component-tests/community-component-tests/__snapshots__/community-list-item.spec.js.snap b/tests/unit/component-tests/community-component-tests/__snapshots__/community-list-item.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..25c734add5c0ca6ad6f94cec526e074008da6782 --- /dev/null +++ b/tests/unit/component-tests/community-component-tests/__snapshots__/community-list-item.spec.js.snap @@ -0,0 +1,65 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CommunityListItem component renders correctly 1`] = ` +<div + data-v-app="" +> + + + <!-- Main modal --> + <!--v-if--> + + <div + class="bg-white shadow dark:bg-gray-800 select-none cursor-pointer hover:bg-gray-50 flex items-center p-4" + > + <div + class="h-10 w-10 flex flex-col justify-center items-center mr-4" + > + <svg + aria-hidden="true" + fill="none" + stroke="currentColor" + stroke-width="2" + viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" + stroke-linecap="round" + stroke-linejoin="round" + /> + </svg> + <!-- TODO: USE COMMUNITY IMAGE <img alt="Felleskapets bilde" src="@/assets/group.png" /> --> + </div> + <div + class="flex-1 pl-1 overflow-hidden" + > + <div + class="font-medium dark:text-white truncate" + > + string + </div> + </div> + <div + class="flex flex-row justify-center items-center" + > + <svg + aria-hidden="true" + class="max-h-6 max-w-6 shrink m-2" + fill="none" + stroke="currentColor" + stroke-width="2" + viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" + stroke-linecap="round" + stroke-linejoin="round" + /> + </svg> + </div> + </div> + +</div> +`; diff --git a/tests/unit/component-tests/community-component-tests/__snapshots__/community-list.spec.js.snap b/tests/unit/component-tests/community-component-tests/__snapshots__/community-list.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..0feda8234936c3b8b7a1ec27d48066f90615cdaf --- /dev/null +++ b/tests/unit/component-tests/community-component-tests/__snapshots__/community-list.spec.js.snap @@ -0,0 +1,10 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CommunityList component renders correctly 1`] = ` +<ul + grouplist="[object Object],[object Object]" +> + + +</ul> +`; diff --git a/tests/unit/component-tests/community-component-tests/__snapshots__/create-new-group.spec.js.snap b/tests/unit/component-tests/community-component-tests/__snapshots__/create-new-group.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..a9b5043d55edf9d7bd0a52eb64e803ffc04f50e5 --- /dev/null +++ b/tests/unit/component-tests/community-component-tests/__snapshots__/create-new-group.spec.js.snap @@ -0,0 +1,181 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CreateNewGroup elements rendering renders correctly 1`] = ` +<div + class="m-6" +> + <!-- Component heading --> + <div + class="flex justify-center mt-6" + > + <p + class="text-4xl" + > + Opprett Gruppe + </p> + </div> + <!-- Radio boxes --> + <div + class="mt-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + id="radioBoxLabel" + > + Synlighet + </label> + <div + class="form-check" + > + <input + class="form-check-input appearance-none rounded-full h-4 w-4 border border-gray-300 bg-white checked:bg-blue-600 checked:border-blue-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer" + id="flexRadioOpen" + name="flexRadioDefault" + type="radio" + value="Åpen" + /> + <label + class="form-check-label inline-block text-gray-800" + for="flexRadioOpen" + id="radioBoxOpenLabel" + > + Åpen + </label> + </div> + <div + class="form-check" + > + <input + class="form-check-input appearance-none rounded-full h-4 w-4 border border-gray-300 bg-white checked:bg-blue-600 checked:border-blue-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer" + id="flexRadioPrivate" + name="flexRadioDefault" + type="radio" + value="Privat" + /> + <label + class="form-check-label inline-block text-gray-800" + for="flexRadioPrivate" + id="radioBoxPrivateLabel" + > + Privat + </label> + </div> + </div> + <!-- Title --> + <div + class="mt-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + id="titleLabel" + > + Gruppenavn + </label> + <input + class="bg-gray-200 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + id="title" + required="" + type="text" + /> + <!-- error message for title--> + + + </div> + <!-- Place --> + <div + class="mt-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + > + By/Sted + </label> + <input + class="bg-gray-200 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + required="" + type="text" + /> + <!-- error message for place--> + + + </div> + <!-- Description --> + <div + class="mt-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400" + id="descriptionLabel" + > + Beskrivelse + </label> + <textarea + class="block p-2.5 w-full text-sm text-gray-900 bg-gray-200 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + id="description" + required="" + rows="4" + /> + <!-- error message for description --> + + + </div> + <!-- Images --> + <div + class="mt-6" + > + <label + class="block mb-2 text-xl font-medium text-gray-900 dark:text-gray-400" + id="imageLabel" + > + Bilde + </label> + <input + accept="image/png, image/jpeg" + multiple="" + style="display: none;" + type="file" + /> + <!-- Button for adding an image --> + <div + class="inline-flex rounded-md shadow-sm" + > + <div + class="text-red-500 uppercase text-center" + > + midlertidig fjernet + </div> + <!-- <button + @click="$refs.file.click()" + class="text-black bg-gray-200 hover:bg-grey-800 focus:ring-4 focus:outline-none focus:ring-grey-300 font-medium rounded-lg text-sm sm:w-auto px-5 py-2.5 text-center dark:bg-grey-600 dark:hover:bg-grey-700 dark:focus:ring-grey-800 disabled:opacity-50" + :disabled="imageAdded" + > + Velg bilde + </button> --> + <!-- Button for removing an image --> + <button + class="w-1/12 ml-5 text-white bg-white-500 font-medium rounded-lg text-sm" + style="display: none;" + > + <img + alt="Remove icon image" + src="" + /> + </button> + </div> + <!-- Div box for showing all chosen images --> + + + </div> + <!-- Save item button --> + <div + class="flex justify-center mt-10" + > + <button + class="content-center text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" + id="saveButton" + > + Lagre + </button> + </div> +</div> +`; diff --git a/tests/unit/component-tests/community-component-tests/__snapshots__/item-card.spec.js.snap b/tests/unit/component-tests/community-component-tests/__snapshots__/item-card.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..a6765453f028760966f7f76701f1f0eea6877ec6 --- /dev/null +++ b/tests/unit/component-tests/community-component-tests/__snapshots__/item-card.spec.js.snap @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ItemCard component renders correctly 1`] = ` +<div + class="mt-5" +> + <div + class="w-52 rounded bg-gray-200" + > + <img + alt="Item image" + class="w-full" + src="String" + /> + <div + class="p-1 m-1" + > + <p + class="text-gray-700 text-xs font-bold" + id="adress" + > + String + </p> + <p + class="font-bold text-sm" + id="title" + > + String + </p> + <p + class="text-gray-700 text-xs" + id="price" + > + 0 kr + </p> + </div> + </div> +</div> +`; diff --git a/tests/unit/component-tests/community-component-tests/__snapshots__/new-item-form.spec.js.snap b/tests/unit/component-tests/community-component-tests/__snapshots__/new-item-form.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..a975fa560f988edeb59aee0a62e951b18b9192e2 --- /dev/null +++ b/tests/unit/component-tests/community-component-tests/__snapshots__/new-item-form.spec.js.snap @@ -0,0 +1,214 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NewItemForm component renders correctly 1`] = ` +<div + class="m-6" +> + <!-- Component heading --> + <div + class="flex justify-center" + > + <p + class="text-4xl mb-6 mt-6" + > + Utleie + </p> + </div> + <!-- Title --> + <div + class="mb-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + id="titleLabel" + > + Tittel + </label> + <input + class="bg-gray-200 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + id="title" + required="" + type="text" + /> + <!-- error message for title--> + + + </div> + <!-- Select category --> + <div + class="mb-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400" + id="selectCategoryLabel" + > + Kategori + </label> + <select + class="bg-gray-200 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + id="categories" + > + <option + class="text-gray-400" + disabled="" + value="" + > + Select a category + </option> + + <option + class="text-gray-900 text-sm" + > + Hage + </option> + <option + class="text-gray-900 text-sm" + > + Kjøkken + </option> + <option + class="text-gray-900 text-sm" + > + Musikk + </option> + <option + class="text-gray-900 text-sm" + > + Annet + </option> + + </select> + <!-- error message for select box --> + + + </div> + <!-- Select Group --> + <div + class="mb-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400" + > + Gruppe + </label> + <select + class="bg-gray-200 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + > + <option + class="text-gray-400" + disabled="" + value="" + > + Select a Group + </option> + + <option + class="text-gray-900 text-sm" + > + 4040 + </option> + <option + class="text-gray-900 text-sm" + > + 4041 + </option> + + </select> + <!-- error message for select box --> + + + </div> + <!-- price --> + <div + class="mb-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + id="priceLabel" + > + Pris + </label> + <input + class="bg-gray-200 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + id="price" + required="" + type="number" + /> + <!-- error message for price --> + + + </div> + <!-- Description --> + <div + class="mb-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400" + id="descriptionLabel" + > + Beskrivelse + </label> + <textarea + class="block p-2.5 w-full text-sm text-gray-900 bg-gray-200 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + id="description" + required="" + rows="4" + /> + <!-- error message for description --> + + + </div> + <!-- Address --> + <div + class="mb-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + > + Adresse + </label> + <input + class="bg-gray-200 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + id="adress" + required="" + type="text" + /> + <!-- error message for address--> + + + </div> + <!-- Images --> + <div> + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400" + id="imageLabel" + > + Bilder + </label> + <input + accept="image/png, image/jpeg" + multiple="" + style="display: none;" + type="file" + /> + <button + class="text-black bg-gray-200 hover:bg-grey-800 focus:ring-4 focus:outline-none focus:ring-grey-300 font-medium rounded-lg text-sm sm:w-auto px-5 py-2.5 text-center dark:bg-grey-600 dark:hover:bg-grey-700 dark:focus:ring-grey-800" + > + Velg bilde + </button> + + + </div> + <!-- Save item button --> + <div + class="flex justify-center" + > + <button + class="content-center text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" + id="saveButton" + > + Lagre + </button> + </div> +</div> +`; diff --git a/tests/unit/component-tests/community-component-tests/__snapshots__/search-item-list.spec.js.snap b/tests/unit/component-tests/community-component-tests/__snapshots__/search-item-list.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..d00db1aa89b9e18df7639635f6bf0fe7b6de9820 --- /dev/null +++ b/tests/unit/component-tests/community-component-tests/__snapshots__/search-item-list.spec.js.snap @@ -0,0 +1,55 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SearchItemListComponent elements rendering renders correctly 1`] = ` +<section + class="relative w-full max-w-md px-5 py-4 mx-auto rounded-md" +> + <div + class="relative" + id="searchComponent" + > + <span + class="absolute inset-y-0 left-0 flex items-center pl-3" + > + <svg + class="w-5 h-5 text-gray-400" + fill="none" + viewBox="0 0 24 24" + > + <path + d="M21 21L15 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z" + stroke="currentColor" + stroke-linecap="round" + stroke-linejoin="round" + stroke-width="2" + /> + </svg> + </span> + <input + class="w-full py-3 pl-10 pr-4 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring" + id="searchInput" + placeholder="Search" + type="text" + /> + </div> + <div + class="absolute inset-x-0 px-6 py-3 mt-4 border-2 border-slate-500" + > + <div + class="grid grid-cols-2" + > + + <item-card-stub + item="[object Object]" + /> + <item-card-stub + item="[object Object]" + /> + <item-card-stub + item="[object Object]" + /> + + </div> + </div> +</section> +`; diff --git a/tests/unit/add-new-item.spec.js b/tests/unit/component-tests/community-component-tests/add-new-item.spec.js similarity index 100% rename from tests/unit/add-new-item.spec.js rename to tests/unit/component-tests/community-component-tests/add-new-item.spec.js diff --git a/tests/unit/component-tests/community-component-tests/community-hamburger.spec.js b/tests/unit/component-tests/community-component-tests/community-hamburger.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..a6834e8680d1d61c29962436e568165fb8c2b937 --- /dev/null +++ b/tests/unit/component-tests/community-component-tests/community-hamburger.spec.js @@ -0,0 +1,13 @@ +import { shallowMount } from "@vue/test-utils"; +import CommunityHamburger from "@/components/CommunityComponents/CommunityHamburger.vue"; + +describe("CommunityHamburger elements rendering", () => { + it("renders all li fields", () => { + const wrapper = shallowMount(CommunityHamburger); + + expect(wrapper.find("#newItem").text()).toMatch("Opprett Utleie"); + expect(wrapper.find("#getMembers").text()).toMatch("Se Medlemmer"); + expect(wrapper.find("#adminGroup").text()).toMatch("Administrer Gruppe"); + expect(wrapper.find("#leaveGroup").text()).toMatch("Forlat Gruppe"); + }); +}); diff --git a/tests/unit/component-tests/community-component-tests/community-list-item.spec.js b/tests/unit/component-tests/community-component-tests/community-list-item.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..3610f19312ab656bfbe7881c21e072626b164cb1 --- /dev/null +++ b/tests/unit/component-tests/community-component-tests/community-list-item.spec.js @@ -0,0 +1,31 @@ +import { mount } from "@vue/test-utils"; +import CommunityListItem from "@/components/CommunityComponents/CommunityListItem.vue"; + +describe("CommunityListItem component", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(CommunityListItem, { + //passing prop to component + props: { + community: { + communityId: 0, + name: "string", + description: "string", + visibility: 0, + location: "string", + picture: "string", + }, + member: false, + }, + }); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/component-tests/community-component-tests/community-list.spec.js b/tests/unit/component-tests/community-component-tests/community-list.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..fbd0968070e19814478e839c92245089f09013b8 --- /dev/null +++ b/tests/unit/component-tests/community-component-tests/community-list.spec.js @@ -0,0 +1,39 @@ +import { mount } from "@vue/test-utils"; +import CommunityList from "@/components/CommunityComponents/CommunityList.vue"; + +describe("CommunityList component", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(CommunityList, { + props: { + groupList: [ + { + communityId: 0, + name: "string", + description: "string", + visibility: 0, + location: "string", + picture: "string", + }, + { + communityId: 0, + name: "string", + description: "string", + visibility: 0, + location: "string", + picture: "string", + }, + ], + }, + }); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/create-new-group.spec.js b/tests/unit/component-tests/community-component-tests/create-new-group.spec.js similarity index 89% rename from tests/unit/create-new-group.spec.js rename to tests/unit/component-tests/community-component-tests/create-new-group.spec.js index 9ff1f2f8c528a002ee52b053533cf8df7ac78150..2110350f78d1d1703141561173eb1727e602d26e 100644 --- a/tests/unit/create-new-group.spec.js +++ b/tests/unit/component-tests/community-component-tests/create-new-group.spec.js @@ -2,9 +2,17 @@ import { shallowMount } from "@vue/test-utils"; import CreateNewGroup from "@/components/CommunityComponents/NewCommunityForm.vue"; describe("CreateNewGroup elements rendering", () => { - it("renders all labels", () => { - const wrapper = shallowMount(CreateNewGroup); + let wrapper; + + beforeEach(() => { + wrapper = shallowMount(CreateNewGroup); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + it("renders all labels", () => { expect(wrapper.find("#radioBoxLabel").text()).toMatch("Synlighet"); expect(wrapper.find("#radioBoxOpenLabel").text()).toMatch("Åpen"); expect(wrapper.find("#radioBoxPrivateLabel").text()).toMatch("Privat"); @@ -14,8 +22,6 @@ describe("CreateNewGroup elements rendering", () => { }); it("Tests setting values of input field", async () => { - const wrapper = shallowMount(CreateNewGroup); - const titleInput = wrapper.find("#title"); await titleInput.setValue("Fjellgata"); expect(titleInput.element.value).toBe("Fjellgata"); @@ -26,8 +32,6 @@ describe("CreateNewGroup elements rendering", () => { }); it("Tests if radio box checks", async () => { - const wrapper = shallowMount(CreateNewGroup); - const radioInputOpen = wrapper.find("#flexRadioOpen"); await radioInputOpen.setChecked(); expect(radioInputOpen.element.checked).toBeTruthy(); diff --git a/tests/unit/component-tests/community-component-tests/item-card.spec.js b/tests/unit/component-tests/community-component-tests/item-card.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..a03b348b8070bd4b572f33ec33d2aa641253458c --- /dev/null +++ b/tests/unit/component-tests/community-component-tests/item-card.spec.js @@ -0,0 +1,27 @@ +import { mount } from "@vue/test-utils"; +import ItemCard from "@/components/CommunityComponents/ItemCard.vue"; + +describe("ItemCard component", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(ItemCard, { + props: { + item: { + img: "String", + address: "String", + title: "String", + pricePerDay: 0, + }, + }, + }); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/component-tests/community-component-tests/new-item-form.spec.js b/tests/unit/component-tests/community-component-tests/new-item-form.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..8271342651aaae430c68cbac6f3a924b482384e1 --- /dev/null +++ b/tests/unit/component-tests/community-component-tests/new-item-form.spec.js @@ -0,0 +1,18 @@ +import { mount } from "@vue/test-utils"; +import NewItemForm from "@/components/CommunityComponents/NewItemForm.vue"; + +describe("NewItemForm component", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(NewItemForm); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/search-item-list.spec.js b/tests/unit/component-tests/community-component-tests/search-item-list.spec.js similarity index 52% rename from tests/unit/search-item-list.spec.js rename to tests/unit/component-tests/community-component-tests/search-item-list.spec.js index 1ad4cff4313ee641059e386856a18e79fa2f7a0f..145a56a66093be7fb062785bafbd11fa6c116f7a 100644 --- a/tests/unit/search-item-list.spec.js +++ b/tests/unit/component-tests/community-component-tests/search-item-list.spec.js @@ -1,10 +1,22 @@ import { shallowMount } from "@vue/test-utils"; import SearchItemListComponent from "@/components/CommunityComponents/SearchItemList.vue"; -describe("CreateNewGroup elements rendering", () => { - it("Tests setting values of input field", async () => { - const wrapper = shallowMount(SearchItemListComponent); +describe("SearchItemListComponent elements rendering", () => { + let wrapper; + + beforeEach(() => { + wrapper = shallowMount(SearchItemListComponent); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); + it("Tests setting values of input field", async () => { const searchInput = wrapper.find("#searchInput"); await searchInput.setValue("Dyson"); expect(searchInput.element.value).toBe("Dyson"); diff --git a/tests/unit/component-tests/user-component-tests/__snapshots__/login-form.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/login-form.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..c712a500effa0e3f64c2187aaa330efdc6fb68a6 --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/__snapshots__/login-form.spec.js.snap @@ -0,0 +1,101 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`LoginForm component renders correctly 1`] = ` +<div + class="max-w-md p-6 mx-auto rounded-md shadow-lg mt-16" +> + <div + class="flex justify-center text-2xl" + > + Logg inn + </div> + <div + class="m-6" + id="emailField" + > + <div + class="mb-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + for="email" + > + E-post + </label> + <input + class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + id="email" + placeholder="eksempel@eksempel.no" + required="" + type="email" + /> + <!-- error message --> + + + </div> + </div> + <div + class="m-6" + id="passwordField" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + for="password" + > + Passord + </label> + <input + class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" + id="password" + required="" + type="password" + /> + <!-- error message --> + + + </div> + <div + class="m-6" + id="buttonsField" + > + <div + class="align-items: flex-end; mb-6" + > + <div + class="ml-3 text-sm" + > + <router-link + class="text-blue-600 flex justify-end" + to="/resetPassword" + > + Glemt passord + </router-link> + </div> + </div> + <button + class="w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5" + > + Logg inn + </button> + <div + class="align-items: flex-end; mb-6 mt-12" + > + <div + class="text-sm" + > + <router-link + class="text-blue-600 flex justify-center" + to="register" + > + Ny bruker + </router-link> + </div> + </div> + <div + class="flex justify-center" + > + <label /> + </div> + </div> +</div> +`; diff --git a/tests/unit/component-tests/user-component-tests/__snapshots__/new-password-form.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/new-password-form.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..8ecfffa14f203f189c5ed8a266f9787f14eeb86d --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/__snapshots__/new-password-form.spec.js.snap @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NewPasswordForm component renders correctly 1`] = ` +<div + class="w-full max-w-sm p-6 m-auto bg-white rounded-md shadow-md dark:bg-gray-800 mt-8" +> + <div + class="" + id="firstPasswordField" + > + <label + class="block text-sm text-gray-800 dark:text-gray-200" + for="password" + > + Nytt passord + </label> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-blue-300 focus:outline-none focus:ring focus:ring-opacity-40" + type="password" + /> + <!-- error message --> + + + </div> + <div + class="mt-4" + id="secondPasswordField" + > + <div + class="flex items-center justify-between" + > + <label + class="block text-sm text-gray-800 dark:text-gray-200" + for="rePassword" + > + Gjenta nytt passord + </label> + </div> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-blue-300 focus:outline-none focus:ring focus:ring-opacity-40" + type="password" + /> + <!-- error message --> + + + </div> + <div + class="mt-6" + id="buttonsField" + > + <button + class="w-full px-4 py-2 tracking-wide text-white transition-colors duration-200 transform bg-gray-700 rounded-md hover:bg-gray-600 focus:outline-none focus:bg-gray-600" + > + Endre passord + </button> + </div> +</div> +`; diff --git a/tests/unit/component-tests/user-component-tests/__snapshots__/rating.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/rating.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..e7d04a61c2d249a8bda1825ed17ed7be65bcf319 --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/__snapshots__/rating.spec.js.snap @@ -0,0 +1,84 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Rating component renders correctly 1`] = ` +<ul + class="flex justify-center" +> + <li> + <p + class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400" + > + : + </p> + </li> + + <li> + <svg + class="w-5 h-5 text-gray-300 dark:text-gray-500" + fill="currentColor" + viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" + /> + </svg> + </li> + <li> + <svg + class="w-5 h-5 text-gray-300 dark:text-gray-500" + fill="currentColor" + viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" + /> + </svg> + </li> + <li> + <svg + class="w-5 h-5 text-gray-300 dark:text-gray-500" + fill="currentColor" + viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" + /> + </svg> + </li> + <li> + <svg + class="w-5 h-5 text-gray-300 dark:text-gray-500" + fill="currentColor" + viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" + /> + </svg> + </li> + <li> + <svg + class="w-5 h-5 text-gray-300 dark:text-gray-500" + fill="currentColor" + viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" + /> + </svg> + </li> + + <li> + <p + class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400" + > + out of 5 + </p> + </li> +</ul> +`; diff --git a/tests/unit/__snapshots__/RegisterUserComponent.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/register-user-component.spec.js.snap similarity index 100% rename from tests/unit/__snapshots__/RegisterUserComponent.spec.js.snap rename to tests/unit/component-tests/user-component-tests/__snapshots__/register-user-component.spec.js.snap diff --git a/tests/unit/component-tests/user-component-tests/__snapshots__/reset-password-form.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/reset-password-form.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..e2fd53153e1a948a06f396c1f77ad5b978e48eb0 --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/__snapshots__/reset-password-form.spec.js.snap @@ -0,0 +1,38 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ResetPasswordForm component renders correctly 1`] = ` +<div + class="resetPassword" +> + <div + class="m-6" + id="emailField" + > + <div + class="mb-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + for="email" + > + E-post + </label> + <input + class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + id="email" + placeholder="eksempel@eksempel.no" + required="" + type="email" + /> + <!-- error message --> + + + </div> + </div> + <button + class="flex justify-center align-items: flex-end; text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" + > + Send e-post + </button> +</div> +`; diff --git a/tests/unit/component-tests/user-component-tests/login-form.spec.js b/tests/unit/component-tests/user-component-tests/login-form.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..40fa711393e969435a609474c0f550f179513135 --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/login-form.spec.js @@ -0,0 +1,18 @@ +import { mount } from "@vue/test-utils"; +import LoginForm from "@/components/FormComponents/LoginForm.vue"; + +describe("LoginForm component", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(LoginForm); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/component-tests/user-component-tests/new-password-form.spec.js b/tests/unit/component-tests/user-component-tests/new-password-form.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..638e597bd9b130a6b2a1c69a0b724b3414436648 --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/new-password-form.spec.js @@ -0,0 +1,18 @@ +import { mount } from "@vue/test-utils"; +import NewPasswordForm from "@/components/FormComponents/NewPasswordForm.vue"; + +describe("NewPasswordForm component", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(NewPasswordForm); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/component-tests/user-component-tests/rating.spec.js b/tests/unit/component-tests/user-component-tests/rating.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..cdbcee60fc44be8c4e04b9f2dc4a42756f5a6699 --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/rating.spec.js @@ -0,0 +1,18 @@ +import { mount } from "@vue/test-utils"; +import Rating from "@/components/UserProfileComponents/Rating.vue"; + +describe("Rating component", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(Rating); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/tests/unit/RegisterUserComponent.spec.js b/tests/unit/component-tests/user-component-tests/register-user-component.spec.js similarity index 100% rename from tests/unit/RegisterUserComponent.spec.js rename to tests/unit/component-tests/user-component-tests/register-user-component.spec.js diff --git a/tests/unit/component-tests/user-component-tests/reset-password-form.spec.js b/tests/unit/component-tests/user-component-tests/reset-password-form.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..1dc9f0a4f379129d888436a42d40bf354ae56f66 --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/reset-password-form.spec.js @@ -0,0 +1,18 @@ +import { mount } from "@vue/test-utils"; +import ResetPasswordForm from "@/components/FormComponents/ResetPasswordForm.vue"; + +describe("ResetPasswordForm component", () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(ResetPasswordForm); + }); + + it("renders correctly", () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it("is instantiated", () => { + expect(wrapper.exists()).toBeTruthy(); + }); +}); diff --git a/vue.config.js b/vue.config.js index e5c2653994c18b4929deb9393289529e17b15c15..3ec0170c3cb07b201b38bd62b0da6f140b0713a9 100644 --- a/vue.config.js +++ b/vue.config.js @@ -1,10 +1,11 @@ const { defineConfig } = require("@vue/cli-service"); + module.exports = defineConfig({ transpileDependencies: true, - - pluginOptions: { - vuetify: { - // https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vuetify-loader - }, + chainWebpack: (config) => { + config.plugin("html").tap((args) => { + args[0].title = "Borrow Company"; + return args; + }); }, });