updated frontend from typescript to javascript
@@ -9,8 +9,10 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@popperjs/core": "^2.10.2",
|
"@popperjs/core": "^2.10.2",
|
||||||
|
"axios": "^0.22.0",
|
||||||
"bootstrap": "^5.1.1",
|
"bootstrap": "^5.1.1",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
|
"luxon": "^2.0.2",
|
||||||
"vue": "^3.0.0",
|
"vue": "^3.0.0",
|
||||||
"vue-router": "^4.0.0-0",
|
"vue-router": "^4.0.0-0",
|
||||||
"vuex": "^4.0.0-0"
|
"vuex": "^4.0.0-0"
|
||||||
@@ -25,6 +27,8 @@
|
|||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"eslint": "^6.7.2",
|
"eslint": "^6.7.2",
|
||||||
"eslint-plugin-vue": "^7.0.0",
|
"eslint-plugin-vue": "^7.0.0",
|
||||||
"sass-loader": "^12.1.0"
|
"sass": "^1.42.1",
|
||||||
|
"sass-loader": "^10.2.0",
|
||||||
|
"string-sanitizer": "^2.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
98
pnpm-lock.yaml
generated
@@ -8,20 +8,26 @@ specifiers:
|
|||||||
'@vue/cli-plugin-vuex': ~4.5.0
|
'@vue/cli-plugin-vuex': ~4.5.0
|
||||||
'@vue/cli-service': ~4.5.0
|
'@vue/cli-service': ~4.5.0
|
||||||
'@vue/compiler-sfc': ^3.0.0
|
'@vue/compiler-sfc': ^3.0.0
|
||||||
|
axios: ^0.22.0
|
||||||
babel-eslint: ^10.1.0
|
babel-eslint: ^10.1.0
|
||||||
bootstrap: ^5.1.1
|
bootstrap: ^5.1.1
|
||||||
core-js: ^3.6.5
|
core-js: ^3.6.5
|
||||||
eslint: ^6.7.2
|
eslint: ^6.7.2
|
||||||
eslint-plugin-vue: ^7.0.0
|
eslint-plugin-vue: ^7.0.0
|
||||||
sass-loader: ^12.1.0
|
luxon: ^2.0.2
|
||||||
|
sass: ^1.42.1
|
||||||
|
sass-loader: ^10.2.0
|
||||||
|
string-sanitizer: ^2.0.2
|
||||||
vue: ^3.0.0
|
vue: ^3.0.0
|
||||||
vue-router: ^4.0.0-0
|
vue-router: ^4.0.0-0
|
||||||
vuex: ^4.0.0-0
|
vuex: ^4.0.0-0
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@popperjs/core': 2.10.2
|
'@popperjs/core': 2.10.2
|
||||||
|
axios: 0.22.0
|
||||||
bootstrap: 5.1.1_@popperjs+core@2.10.2
|
bootstrap: 5.1.1_@popperjs+core@2.10.2
|
||||||
core-js: 3.18.1
|
core-js: 3.18.1
|
||||||
|
luxon: 2.0.2
|
||||||
vue: 3.2.19
|
vue: 3.2.19
|
||||||
vue-router: 4.0.11_vue@3.2.19
|
vue-router: 4.0.11_vue@3.2.19
|
||||||
vuex: 4.0.2_vue@3.2.19
|
vuex: 4.0.2_vue@3.2.19
|
||||||
@@ -31,12 +37,14 @@ devDependencies:
|
|||||||
'@vue/cli-plugin-eslint': 4.5.13_a58cf9e4d577795b8c257bee96d49483
|
'@vue/cli-plugin-eslint': 4.5.13_a58cf9e4d577795b8c257bee96d49483
|
||||||
'@vue/cli-plugin-router': 4.5.13_@vue+cli-service@4.5.13
|
'@vue/cli-plugin-router': 4.5.13_@vue+cli-service@4.5.13
|
||||||
'@vue/cli-plugin-vuex': 4.5.13_@vue+cli-service@4.5.13
|
'@vue/cli-plugin-vuex': 4.5.13_@vue+cli-service@4.5.13
|
||||||
'@vue/cli-service': 4.5.13_0c7cfb9d6b60c37eed7038267d6bc444
|
'@vue/cli-service': 4.5.13_14d4d8446413226c330137c0feac1b91
|
||||||
'@vue/compiler-sfc': 3.2.19
|
'@vue/compiler-sfc': 3.2.19
|
||||||
babel-eslint: 10.1.0_eslint@6.8.0
|
babel-eslint: 10.1.0_eslint@6.8.0
|
||||||
eslint: 6.8.0
|
eslint: 6.8.0
|
||||||
eslint-plugin-vue: 7.18.0_eslint@6.8.0
|
eslint-plugin-vue: 7.18.0_eslint@6.8.0
|
||||||
sass-loader: 12.1.0
|
sass: 1.42.1
|
||||||
|
sass-loader: 10.2.0_sass@1.42.1
|
||||||
|
string-sanitizer: 2.0.2
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@@ -1565,7 +1573,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.15.5
|
'@babel/core': 7.15.5
|
||||||
'@vue/babel-preset-app': 4.5.13_vue@3.2.19
|
'@vue/babel-preset-app': 4.5.13_vue@3.2.19
|
||||||
'@vue/cli-service': 4.5.13_0c7cfb9d6b60c37eed7038267d6bc444
|
'@vue/cli-service': 4.5.13_14d4d8446413226c330137c0feac1b91
|
||||||
'@vue/cli-shared-utils': 4.5.13
|
'@vue/cli-shared-utils': 4.5.13
|
||||||
babel-loader: 8.2.2_99877201e3f6dd5396b321f0a88244ea
|
babel-loader: 8.2.2_99877201e3f6dd5396b321f0a88244ea
|
||||||
cache-loader: 4.1.0_webpack@4.46.0
|
cache-loader: 4.1.0_webpack@4.46.0
|
||||||
@@ -1584,7 +1592,7 @@ packages:
|
|||||||
'@vue/cli-service': ^3.0.0 || ^4.0.0-0
|
'@vue/cli-service': ^3.0.0 || ^4.0.0-0
|
||||||
eslint: '>= 1.6.0 < 7.0.0'
|
eslint: '>= 1.6.0 < 7.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/cli-service': 4.5.13_0c7cfb9d6b60c37eed7038267d6bc444
|
'@vue/cli-service': 4.5.13_14d4d8446413226c330137c0feac1b91
|
||||||
'@vue/cli-shared-utils': 4.5.13
|
'@vue/cli-shared-utils': 4.5.13
|
||||||
eslint: 6.8.0
|
eslint: 6.8.0
|
||||||
eslint-loader: 2.2.1_eslint@6.8.0+webpack@4.46.0
|
eslint-loader: 2.2.1_eslint@6.8.0+webpack@4.46.0
|
||||||
@@ -1602,7 +1610,7 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@vue/cli-service': ^3.0.0 || ^4.0.0-0
|
'@vue/cli-service': ^3.0.0 || ^4.0.0-0
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/cli-service': 4.5.13_0c7cfb9d6b60c37eed7038267d6bc444
|
'@vue/cli-service': 4.5.13_14d4d8446413226c330137c0feac1b91
|
||||||
'@vue/cli-shared-utils': 4.5.13
|
'@vue/cli-shared-utils': 4.5.13
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -1611,10 +1619,10 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@vue/cli-service': ^3.0.0 || ^4.0.0-0
|
'@vue/cli-service': ^3.0.0 || ^4.0.0-0
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/cli-service': 4.5.13_0c7cfb9d6b60c37eed7038267d6bc444
|
'@vue/cli-service': 4.5.13_14d4d8446413226c330137c0feac1b91
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@vue/cli-service/4.5.13_0c7cfb9d6b60c37eed7038267d6bc444:
|
/@vue/cli-service/4.5.13_14d4d8446413226c330137c0feac1b91:
|
||||||
resolution: {integrity: sha512-CKAZN4iokMMsaUyJRU22oUAz3oS/X9sVBSKAF2/shFBV5xh3jqAlKl8OXZYz4cXGFLA6djNuYrniuLAo7Ku97A==}
|
resolution: {integrity: sha512-CKAZN4iokMMsaUyJRU22oUAz3oS/X9sVBSKAF2/shFBV5xh3jqAlKl8OXZYz4cXGFLA6djNuYrniuLAo7Ku97A==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -1687,7 +1695,7 @@ packages:
|
|||||||
pnp-webpack-plugin: 1.7.0
|
pnp-webpack-plugin: 1.7.0
|
||||||
portfinder: 1.0.28
|
portfinder: 1.0.28
|
||||||
postcss-loader: 3.0.0
|
postcss-loader: 3.0.0
|
||||||
sass-loader: 12.1.0
|
sass-loader: 10.2.0_sass@1.42.1
|
||||||
ssri: 8.0.1
|
ssri: 8.0.1
|
||||||
terser-webpack-plugin: 1.4.5_webpack@4.46.0
|
terser-webpack-plugin: 1.4.5_webpack@4.46.0
|
||||||
thread-loader: 2.1.3_webpack@4.46.0
|
thread-loader: 2.1.3_webpack@4.46.0
|
||||||
@@ -2245,6 +2253,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==}
|
resolution: {integrity: sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/axios/0.22.0:
|
||||||
|
resolution: {integrity: sha512-Z0U3uhqQeg1oNcihswf4ZD57O3NrR1+ZXhxaROaWpDmsDTx7T2HNBV2ulBtie2hwJptu8UvgnJoK+BIqdzh/1w==}
|
||||||
|
dependencies:
|
||||||
|
follow-redirects: 1.14.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- debug
|
||||||
|
dev: false
|
||||||
|
|
||||||
/babel-eslint/10.1.0_eslint@6.8.0:
|
/babel-eslint/10.1.0_eslint@6.8.0:
|
||||||
resolution: {integrity: sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==}
|
resolution: {integrity: sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -2378,7 +2394,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dev: true
|
dev: true
|
||||||
optional: true
|
|
||||||
|
|
||||||
/bindings/1.5.0:
|
/bindings/1.5.0:
|
||||||
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
|
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
|
||||||
@@ -2761,7 +2776,6 @@ packages:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.2
|
fsevents: 2.3.2
|
||||||
dev: true
|
dev: true
|
||||||
optional: true
|
|
||||||
|
|
||||||
/chownr/1.1.4:
|
/chownr/1.1.4:
|
||||||
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
|
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
|
||||||
@@ -4280,7 +4294,7 @@ packages:
|
|||||||
readable-stream: 2.3.7
|
readable-stream: 2.3.7
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/follow-redirects/1.14.4_debug@4.3.2:
|
/follow-redirects/1.14.4:
|
||||||
resolution: {integrity: sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==}
|
resolution: {integrity: sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==}
|
||||||
engines: {node: '>=4.0'}
|
engines: {node: '>=4.0'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -4288,9 +4302,6 @@ packages:
|
|||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
debug:
|
debug:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
|
||||||
debug: 4.3.2
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/for-in/1.0.2:
|
/for-in/1.0.2:
|
||||||
resolution: {integrity: sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=}
|
resolution: {integrity: sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=}
|
||||||
@@ -4807,7 +4818,7 @@ packages:
|
|||||||
engines: {node: '>=8.0.0'}
|
engines: {node: '>=8.0.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
eventemitter3: 4.0.7
|
eventemitter3: 4.0.7
|
||||||
follow-redirects: 1.14.4_debug@4.3.2
|
follow-redirects: 1.14.4
|
||||||
requires-port: 1.0.0
|
requires-port: 1.0.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- debug
|
- debug
|
||||||
@@ -5042,7 +5053,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
binary-extensions: 2.2.0
|
binary-extensions: 2.2.0
|
||||||
dev: true
|
dev: true
|
||||||
optional: true
|
|
||||||
|
|
||||||
/is-boolean-object/1.1.2:
|
/is-boolean-object/1.1.2:
|
||||||
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
|
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
|
||||||
@@ -5535,7 +5545,6 @@ packages:
|
|||||||
emojis-list: 3.0.0
|
emojis-list: 3.0.0
|
||||||
json5: 2.2.0
|
json5: 2.2.0
|
||||||
dev: true
|
dev: true
|
||||||
optional: true
|
|
||||||
|
|
||||||
/locate-path/3.0.0:
|
/locate-path/3.0.0:
|
||||||
resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==}
|
resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==}
|
||||||
@@ -5613,6 +5622,17 @@ packages:
|
|||||||
yallist: 3.1.1
|
yallist: 3.1.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/lru-cache/6.0.0:
|
||||||
|
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
dependencies:
|
||||||
|
yallist: 4.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/luxon/2.0.2:
|
||||||
|
resolution: {integrity: sha512-ZRioYLCgRHrtTORaZX1mx+jtxKtKuI5ZDvHNAmqpUzGqSrR+tL4FVLn/CUGMA3h0+AKD1MAxGI5GnCqR5txNqg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/magic-string/0.25.7:
|
/magic-string/0.25.7:
|
||||||
resolution: {integrity: sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==}
|
resolution: {integrity: sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -7078,7 +7098,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
picomatch: 2.3.0
|
picomatch: 2.3.0
|
||||||
dev: true
|
dev: true
|
||||||
optional: true
|
|
||||||
|
|
||||||
/regenerate-unicode-properties/9.0.0:
|
/regenerate-unicode-properties/9.0.0:
|
||||||
resolution: {integrity: sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==}
|
resolution: {integrity: sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==}
|
||||||
@@ -7334,14 +7353,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/sass-loader/12.1.0:
|
/sass-loader/10.2.0_sass@1.42.1:
|
||||||
resolution: {integrity: sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg==}
|
resolution: {integrity: sha512-kUceLzC1gIHz0zNJPpqRsJyisWatGYNFRmv2CKZK2/ngMJgLqxTbXwe/hJ85luyvZkgqU3VlJ33UVF2T/0g6mw==}
|
||||||
engines: {node: '>= 12.13.0'}
|
engines: {node: '>= 10.13.0'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
fibers: '>= 3.1.0'
|
fibers: '>= 3.1.0'
|
||||||
node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0
|
node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0
|
||||||
sass: ^1.3.0
|
sass: ^1.3.0
|
||||||
webpack: ^5.0.0
|
webpack: ^4.36.0 || ^5.0.0
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
fibers:
|
fibers:
|
||||||
optional: true
|
optional: true
|
||||||
@@ -7351,7 +7370,19 @@ packages:
|
|||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
klona: 2.0.4
|
klona: 2.0.4
|
||||||
|
loader-utils: 2.0.0
|
||||||
neo-async: 2.6.2
|
neo-async: 2.6.2
|
||||||
|
sass: 1.42.1
|
||||||
|
schema-utils: 3.1.1
|
||||||
|
semver: 7.3.5
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/sass/1.42.1:
|
||||||
|
resolution: {integrity: sha512-/zvGoN8B7dspKc5mC6HlaygyCBRvnyzzgD5khiaCfglWztY99cYoiTUksVx11NlnemrcfH5CEaCpsUKoW0cQqg==}
|
||||||
|
engines: {node: '>=8.9.0'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
chokidar: 3.5.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/sax/1.2.4:
|
/sax/1.2.4:
|
||||||
@@ -7376,6 +7407,15 @@ packages:
|
|||||||
ajv-keywords: 3.5.2_ajv@6.12.6
|
ajv-keywords: 3.5.2_ajv@6.12.6
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/schema-utils/3.1.1:
|
||||||
|
resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==}
|
||||||
|
engines: {node: '>= 10.13.0'}
|
||||||
|
dependencies:
|
||||||
|
'@types/json-schema': 7.0.9
|
||||||
|
ajv: 6.12.6
|
||||||
|
ajv-keywords: 3.5.2_ajv@6.12.6
|
||||||
|
dev: true
|
||||||
|
|
||||||
/select-hose/2.0.0:
|
/select-hose/2.0.0:
|
||||||
resolution: {integrity: sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=}
|
resolution: {integrity: sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -7401,6 +7441,14 @@ packages:
|
|||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/semver/7.3.5:
|
||||||
|
resolution: {integrity: sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
lru-cache: 6.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/send/0.17.1:
|
/send/0.17.1:
|
||||||
resolution: {integrity: sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==}
|
resolution: {integrity: sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@@ -7792,6 +7840,10 @@ packages:
|
|||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/string-sanitizer/2.0.2:
|
||||||
|
resolution: {integrity: sha512-zECtWmUawolaVbUOdDRdhAM4jN7wl1sB4indjTmHpUFavzFSeYEDSVF85dZPPyDKoMRTJbrz+Tp0SjPPCWxscA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/string-width/2.1.1:
|
/string-width/2.1.1:
|
||||||
resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==}
|
resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
21
scss/custom.scss
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Custom.scss
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap');
|
||||||
|
|
||||||
|
// Default variable overrides
|
||||||
|
$font-family-base: 'Roboto';
|
||||||
|
//$primary: #292c34;
|
||||||
|
//$secondary: #23262d;
|
||||||
|
//$body-bg: #2e3139;
|
||||||
|
//$blue: #4a90e2;
|
||||||
|
$body-color: white;
|
||||||
|
|
||||||
|
$primary: #888f98;
|
||||||
|
$secondary: #10121a;
|
||||||
|
$body-bg: #1b2732;
|
||||||
|
$blue: #5f7892;
|
||||||
|
$warning: #c3a235;
|
||||||
|
$info: $blue;
|
||||||
|
$success: #609926;
|
||||||
|
|
||||||
|
// Bootstrap
|
||||||
|
@import "../node_modules/bootstrap/scss/bootstrap";
|
24
src/App.vue
@@ -1,3 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<header>
|
||||||
|
<Nav/>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<div class="spacer bg-secondary"></div>
|
||||||
<router-view/>
|
<router-view/>
|
||||||
|
</main>
|
||||||
|
<footer>
|
||||||
|
<Footer />
|
||||||
|
</footer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Nav from "@/components/Nav";
|
||||||
|
import Footer from "@/components/Footer";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {Footer, Nav},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.spacer {
|
||||||
|
height: 70px;
|
||||||
|
}
|
||||||
|
</style>
|
31
src/components/Footer.vue
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
<div class="bg-secondary text-center pt-5 pb-4">
|
||||||
|
<div class="icons pb-4">
|
||||||
|
<a class="text-white" target="_blank" href="https://git.harting.dev/CSGOWTF/csgowtf">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-github"
|
||||||
|
viewBox="0 0 16 16">
|
||||||
|
<path
|
||||||
|
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="text">
|
||||||
|
<p>This site is an open source project, originally created and maintained by <span class="text-warning">anonfunc</span> and <span
|
||||||
|
class="text-warning">vikingowl</span>.</p>
|
||||||
|
<p class="text-muted">For feedback contact us at <a class="text-muted text-decoration-none"
|
||||||
|
href="mailto:#">EMAIL</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "Footer",
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
p {
|
||||||
|
font-size: .85rem;
|
||||||
|
}
|
||||||
|
</style>
|
110
src/components/Nav.vue
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
<template>
|
||||||
|
<nav class="navbar navbar-expand navbar-dark fixed-top">
|
||||||
|
<div class="container-fluid w-75">
|
||||||
|
<div class="navbar-nav">
|
||||||
|
<router-link class="navbar-brand text-warning fw-bold fs-3" to="/">CSGO<span class="text-up text-white fw-bold">WTF</span>
|
||||||
|
</router-link>
|
||||||
|
<router-link class="nav-link" to="/explore">Explore</router-link>
|
||||||
|
</div>
|
||||||
|
<form class="d-flex col-5 justify-content-end" @keydown.enter.prevent="parseSearch">
|
||||||
|
<label for="search">
|
||||||
|
<svg class="bi bi-search" fill="currentColor" height="24" viewBox="0 0 16 16" width="24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
|
||||||
|
</svg>
|
||||||
|
</label>
|
||||||
|
<input id="search" v-model="data.searchInput" aria-label="Search"
|
||||||
|
class="form-control w-75 bg-transparent border-0"
|
||||||
|
placeholder="SteamID64, Profile Link or Custom URL"
|
||||||
|
type="search">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {reactive} from "vue";
|
||||||
|
import {useStore} from 'vuex'
|
||||||
|
import {sanitize} from 'string-sanitizer'
|
||||||
|
import router from "../router";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Nav',
|
||||||
|
setup() {
|
||||||
|
const store = useStore()
|
||||||
|
const data = reactive({
|
||||||
|
searchInput: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const parseSearch = () => {
|
||||||
|
const input = data.searchInput
|
||||||
|
const customUrlPattern = 'https://steamcommunity.com/id/'
|
||||||
|
const profileUrlPattern = 'https://steamcommunity.com/profiles/'
|
||||||
|
const id64Pattern = /^\d{17}$/
|
||||||
|
|
||||||
|
store.state.id64 = ''
|
||||||
|
store.state.vanityUrl = ''
|
||||||
|
|
||||||
|
if (id64Pattern.test(input)) {
|
||||||
|
store.state.id64 = input
|
||||||
|
} else if (input.match(customUrlPattern)) {
|
||||||
|
store.state.vanityUrl = sanitize(input.split('/')[4].split('?')[0])
|
||||||
|
} else if (input.match(profileUrlPattern)) {
|
||||||
|
const tmp = input.split('/')[4].split('?')[0]
|
||||||
|
if (id64Pattern.test(tmp)) {
|
||||||
|
store.state.id64 = tmp
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
store.state.vanityUrl = sanitize(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (store.state.id64 !== '' || store.state.vanityUrl !== '') {
|
||||||
|
data.searchInput = ''
|
||||||
|
|
||||||
|
if (store.state.id64) {
|
||||||
|
router.push(`/player/${store.state.id64}`)
|
||||||
|
} else if (store.state.vanityUrl) {
|
||||||
|
router.push(`/player/${store.state.vanityUrl}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
data, parseSearch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
nav {
|
||||||
|
height: 70px;
|
||||||
|
width: 100vw;
|
||||||
|
background: rgba(16, 18, 26, 0.5);
|
||||||
|
|
||||||
|
.text-up {
|
||||||
|
font-size: 40%;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
padding-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="search"] {
|
||||||
|
min-width: 300px;
|
||||||
|
max-width: 300px;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
box-shadow: 0 4px 2px -2px rgba(95, 120, 146, 0.59);
|
||||||
|
transition: .2s ease-in-out;
|
||||||
|
transform: scale(.975);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
71
src/components/ScoreTeam.vue
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="player__avatar"></th>
|
||||||
|
<th class="player__name"></th>
|
||||||
|
<th class="player__rank"></th>
|
||||||
|
<th class="player__kills cursor__help" title="Kills">K</th>
|
||||||
|
<th class="player__assist cursor__help" title="Assists">A</th>
|
||||||
|
<th class="player__deaths cursor__help" title="Deaths">D</th>
|
||||||
|
<th class="player__diff cursor__help" title="Kill death difference">+/-</th>
|
||||||
|
<th class="player__kd cursor__help" title="Kill death ratio">K/D</th>
|
||||||
|
<th class="player__adr cursor__help" title="Average damage per round">ADR</th>
|
||||||
|
<th class="player__hs cursor__help" title="Percentage of kills with a headshot">HS%</th>
|
||||||
|
<th class="player__kast cursor__help" title="Percentage of rounds with a Kill, Assist, Survived or Death Traded">
|
||||||
|
KAST
|
||||||
|
</th>
|
||||||
|
<th class="player__rating cursor__help" title="Estimated HLTV Rating 1.0">Rating</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody v-for="player in props.stats" :key="player.player.steamid64">
|
||||||
|
<tr v-if="player.team_id === props.team_id" class="player">
|
||||||
|
<ScoreTeamPlayer
|
||||||
|
:assists="player.assists"
|
||||||
|
:avatar="player.player.avatar"
|
||||||
|
:deaths="player.deaths"
|
||||||
|
:dmg="player.extended?.dmg?.enemy"
|
||||||
|
:hs="player.headshot"
|
||||||
|
:kast="player.extended?.kast"
|
||||||
|
:kdiff="player.kills - player.deaths"
|
||||||
|
:kills="player.kills"
|
||||||
|
:mk_duo="player.extended?.multi_kills?.duo"
|
||||||
|
:mk_pent="player.extended?.multi_kills?.pent"
|
||||||
|
:mk_quad="player.extended?.multi_kills?.quad"
|
||||||
|
:mk_triple="player.extended?.multi_kills?.triple"
|
||||||
|
:name="player.player.name"
|
||||||
|
:rounds_played="props.rounds_played"
|
||||||
|
:rank="player.extended?.rank?.old"
|
||||||
|
/>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ScoreTeamPlayer from '@/components/ScoreTeamPlayer.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ScoreTeam',
|
||||||
|
components: {ScoreTeamPlayer},
|
||||||
|
props: {
|
||||||
|
stats: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
rounds_played: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
team_id: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
return {props}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
130
src/components/ScoreTeamPlayer.vue
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
<template>
|
||||||
|
<td>
|
||||||
|
<img :src="props.avatar" alt="Player avatar" class="player__avatar">
|
||||||
|
</td>
|
||||||
|
<td class="player__name">
|
||||||
|
{{ props.name }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<img :src="props.rank ? require('@/images/ranks/' + props.rank + '.png') : require('@/images/ranks/0.png')"
|
||||||
|
alt="Player rank"
|
||||||
|
class="player__rank">
|
||||||
|
</td>
|
||||||
|
<td class="player__kills">
|
||||||
|
{{ props.kills }}
|
||||||
|
</td>
|
||||||
|
<td class="player__assist">
|
||||||
|
{{ props.assists }}
|
||||||
|
</td>
|
||||||
|
<td class="player__deaths">
|
||||||
|
{{ props.deaths }}
|
||||||
|
</td>
|
||||||
|
<td :class="props.kdiff >= 0 ? 'text-success' : 'text-danger'" class="player__diff">
|
||||||
|
{{ props.kdiff }}
|
||||||
|
</td>
|
||||||
|
<td class="player__kd">
|
||||||
|
{{ (props.kills > 0 && props.deaths > 0) ? (props.kills / props.deaths).toFixed(2) : (props.kills > 0 && props.deaths === 0) ? props.kills : 0.00 }}
|
||||||
|
</td>
|
||||||
|
<td class="player__adr">
|
||||||
|
{{ (props.dmg / props.rounds_played).toFixed(2) }}
|
||||||
|
</td>
|
||||||
|
<td class="player__hs">
|
||||||
|
{{ (props.hs > 0 && props.kills > 0) ? (props.hs * 100 / props.kills).toFixed(0) + "%" : "0%" }}
|
||||||
|
</td>
|
||||||
|
<td class="player__kast">
|
||||||
|
{{ props.kast ? props.kast + "%" : "-" }}
|
||||||
|
</td>
|
||||||
|
<td class="player__rating">
|
||||||
|
{{
|
||||||
|
GetHLTV_1(props.kills, props.rounds_played, props.deaths, props.mk_duo, props.mk_triple, props.mk_quad, props.mk_pent)
|
||||||
|
}}
|
||||||
|
</td>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {GetHLTV_1} from "../utils";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ScoreTeamPlayer',
|
||||||
|
props: {
|
||||||
|
avatar: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: 'Avatar'
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: 'Name'
|
||||||
|
},
|
||||||
|
rank: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
kills: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
assists: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
deaths: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
kdiff: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
hs: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
rounds_played: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
mk_duo: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
mk_triple: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
mk_quad: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
mk_pent: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
kast: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
dmg: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
return {props, GetHLTV_1}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
3
src/images/icons/gitfork.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M7,12 L14.5,12 C16.277025,12 17.7447372,10.6756742 17.970024,8.96013518 C16.2885152,8.7047201 15,7.25283448 15,5.5 C15,3.56700338 16.5670034,2 18.5,2 C20.4329966,2 22,3.56700338 22,5.5 C22,7.27155475 20.6838151,8.73569805 18.9759671,8.96790818 C18.7419236,11.2333126 16.8272778,13 14.5,13 L7,13 L7,15.0354444 C8.69614707,15.2780593 10,16.736764 10,18.5 C10,20.4329966 8.43299662,22 6.5,22 C4.56700338,22 3,20.4329966 3,18.5 C3,16.736764 4.30385293,15.2780593 6,15.0354444 L6,8.96455557 C4.30385293,8.72194074 3,7.26323595 3,5.5 C3,3.56700338 4.56700338,2 6.5,2 C8.43299662,2 10,3.56700338 10,5.5 C10,7.26323595 8.69614707,8.72194074 7,8.96455557 L7,12 Z M4,18.5 C4,19.8807119 5.11928813,21 6.5,21 C7.88071187,21 9,19.8807119 9,18.5 C9,17.1192881 7.88071187,16 6.5,16 C5.11928813,16 4,17.1192881 4,18.5 Z M4,5.5 C4,6.88071187 5.11928813,8 6.5,8 C7.88071187,8 9,6.88071187 9,5.5 C9,4.11928813 7.88071187,3 6.5,3 C5.11928813,3 4,4.11928813 4,5.5 Z M18.5,3 C17.1192881,3 16,4.11928813 16,5.5 C16,6.88071187 17.1192881,8 18.5,8 C19.8807119,8 21,6.88071187 21,5.5 C21,4.11928813 19.8807119,3 18.5,3 Z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/images/maps/de_inferno.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src/images/maps/de_mirage.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
src/images/maps/de_overpass.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/images/maps/not_found.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
src/images/ranks/0.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
src/images/ranks/1.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
src/images/ranks/10.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
src/images/ranks/11.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
src/images/ranks/12.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
src/images/ranks/13.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
src/images/ranks/14.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src/images/ranks/15.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
src/images/ranks/16.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
src/images/ranks/17.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
src/images/ranks/18.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
src/images/ranks/2.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src/images/ranks/3.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src/images/ranks/4.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
src/images/ranks/5.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
src/images/ranks/6.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
src/images/ranks/7.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
src/images/ranks/8.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
src/images/ranks/9.png
Normal file
After Width: | Height: | Size: 23 KiB |
@@ -2,5 +2,7 @@ import { createApp } from 'vue'
|
|||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
|
import 'bootstrap'
|
||||||
|
import '../scss/custom.scss'
|
||||||
|
|
||||||
createApp(App).use(store).use(router).mount('#app')
|
createApp(App).use(store).use(router).mount('#app')
|
||||||
|
@@ -1,12 +1,43 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import Home from '../views/Home.vue'
|
|
||||||
|
function lazyLoad(view) {
|
||||||
|
return () => import(`@/views/${view}.vue`)
|
||||||
|
}
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'Home',
|
name: 'Home',
|
||||||
component: Home
|
component: lazyLoad('Home')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/player/:id',
|
||||||
|
name: 'Player',
|
||||||
|
component: lazyLoad('Player'),
|
||||||
|
props: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/player/:id/matches',
|
||||||
|
name: 'MyMatches',
|
||||||
|
component: lazyLoad('MyMatches'),
|
||||||
|
props: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/match/:match_id',
|
||||||
|
name: 'Match',
|
||||||
|
component: lazyLoad('Match'),
|
||||||
|
props: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/explore',
|
||||||
|
name: 'Explore',
|
||||||
|
component: lazyLoad('Explore'),
|
||||||
|
props: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/:pathMatch(.*)*',
|
||||||
|
redirect: '/'
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
@@ -2,6 +2,8 @@ import { createStore } from 'vuex'
|
|||||||
|
|
||||||
export default createStore({
|
export default createStore({
|
||||||
state: {
|
state: {
|
||||||
|
id64: '',
|
||||||
|
vanityUrl: ''
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
},
|
},
|
||||||
|
50
src/utils/index.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import {DateTime} from "luxon/build/es6/luxon";
|
||||||
|
import router from '@/router'
|
||||||
|
|
||||||
|
export const FormatDuration = (d) => {
|
||||||
|
const hours = Math.floor(d / 3600)
|
||||||
|
const num = d % 3600
|
||||||
|
const minutes = Math.floor(num % 3600 / 60)
|
||||||
|
const seconds = Math.floor(num % 3600 % 60)
|
||||||
|
|
||||||
|
if (hours !== 0)
|
||||||
|
return `${hours}:${minutes < 10 ? '0' + minutes : minutes}:${seconds < 10 ? '0' + seconds : seconds}`
|
||||||
|
else
|
||||||
|
return `${minutes < 10 ? '0' + minutes : minutes}:${seconds < 10 ? '0' + seconds : seconds}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FormatDate = (date) => {
|
||||||
|
const matchDate = DateTime.fromISO(date)
|
||||||
|
const diff = DateTime.now().diff(matchDate)
|
||||||
|
|
||||||
|
if (diff.as('days') > 10)
|
||||||
|
return matchDate.toLocaleString({weekday: 'short', day: 'numeric', month: 'numeric', year: 'numeric'})
|
||||||
|
else if (diff.as('days') < 1)
|
||||||
|
if (diff.as('hours') < 1)
|
||||||
|
return Math.floor(diff.as('minutes')) + ' minutes ago'
|
||||||
|
else
|
||||||
|
return Math.floor(diff.as('hours')) + ' hours ago'
|
||||||
|
else
|
||||||
|
return Math.floor(diff.as('days')) + ' days ago'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GoToMatch = (id) => {
|
||||||
|
router.push(`/match/${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GoToPlayer = (id) => {
|
||||||
|
router.push(`/player/${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GetHLTV_1 = (kills = 0, rounds, deaths = 0, k2 = 0, k3 = 0, k4 = 0, k5 = 0) => {
|
||||||
|
const k1 = kills - k2 - k3 - k4 - k5
|
||||||
|
const Weight_KPR = 0.679 // weight kills per round
|
||||||
|
const Weight_SPR = 0.317 // weight survived rounds per round
|
||||||
|
const Weight_RMK = 1.277 // weight value calculated from rounds with multiple kills (1k + 4*2k + 9*3k + 16*4k + 25*5k)
|
||||||
|
|
||||||
|
const KillRating = kills / rounds / Weight_KPR
|
||||||
|
const SurvivalRating = (rounds - deaths) / rounds / Weight_SPR
|
||||||
|
const RoundsWithMultipleKillsRating = (k1 + 4 * k2 + 9 * k3 + 16 * k4 + 25 * k5) / rounds / Weight_RMK
|
||||||
|
|
||||||
|
return ((KillRating + 0.7 * SurvivalRating + RoundsWithMultipleKillsRating) / 2.7).toFixed(2)
|
||||||
|
}
|
9
src/views/Explore.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
Explore
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Explore'
|
||||||
|
}
|
||||||
|
</script>
|
@@ -1,3 +1,112 @@
|
|||||||
<template>
|
<template>
|
||||||
Home
|
<div class="main-content content text-center">
|
||||||
|
<div class="head">
|
||||||
|
<h1 class="text-warning fw-bold">CSGO<span class="text-up text-white">WTF</span></h1>
|
||||||
|
<h3>Open source CSGO data platform</h3>
|
||||||
|
</div>
|
||||||
|
<div class="body row m-auto mt-5 mb-5">
|
||||||
|
<div class="col-4">
|
||||||
|
<svg class="mb-4" height="80" viewBox="0 0 24 24" width="80" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M7,12 L14.5,12 C16.277025,12 17.7447372,10.6756742 17.970024,8.96013518 C16.2885152,8.7047201 15,7.25283448 15,5.5 C15,3.56700338 16.5670034,2 18.5,2 C20.4329966,2 22,3.56700338 22,5.5 C22,7.27155475 20.6838151,8.73569805 18.9759671,8.96790818 C18.7419236,11.2333126 16.8272778,13 14.5,13 L7,13 L7,15.0354444 C8.69614707,15.2780593 10,16.736764 10,18.5 C10,20.4329966 8.43299662,22 6.5,22 C4.56700338,22 3,20.4329966 3,18.5 C3,16.736764 4.30385293,15.2780593 6,15.0354444 L6,8.96455557 C4.30385293,8.72194074 3,7.26323595 3,5.5 C3,3.56700338 4.56700338,2 6.5,2 C8.43299662,2 10,3.56700338 10,5.5 C10,7.26323595 8.69614707,8.72194074 7,8.96455557 L7,12 Z M4,18.5 C4,19.8807119 5.11928813,21 6.5,21 C7.88071187,21 9,19.8807119 9,18.5 C9,17.1192881 7.88071187,16 6.5,16 C5.11928813,16 4,17.1192881 4,18.5 Z M4,5.5 C4,6.88071187 5.11928813,8 6.5,8 C7.88071187,8 9,6.88071187 9,5.5 C9,4.11928813 7.88071187,3 6.5,3 C5.11928813,3 4,4.11928813 4,5.5 Z M18.5,3 C17.1192881,3 16,4.11928813 16,5.5 C16,6.88071187 17.1192881,8 18.5,8 C19.8807119,8 21,6.88071187 21,5.5 C21,4.11928813 19.8807119,3 18.5,3 Z"
|
||||||
|
fill="white"/>
|
||||||
|
</svg>
|
||||||
|
<h4 class="fw-light">Open Source</h4>
|
||||||
|
<p class="w-75 m-auto fw-light">All project code is open source and available for contributors to improve and
|
||||||
|
modify.</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-4">
|
||||||
|
<svg class="bi bi-bar-chart-fill mb-4" fill="currentColor" height="80" viewBox="0 0 16 16"
|
||||||
|
width="80" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M1 11a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-3zm5-4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7zm5-5a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1V2z"/>
|
||||||
|
</svg>
|
||||||
|
<h4 class="fw-light">In-Depth Data</h4>
|
||||||
|
<p class="w-75 m-auto fw-light">Parsing replay files provides highly detailed match data.</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-4">
|
||||||
|
<svg class="bi bi-stars mb-4" fill="currentColor" height="80" viewBox="0 0 16 16" width="80"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M7.657 6.247c.11-.33.576-.33.686 0l.645 1.937a2.89 2.89 0 0 0 1.829 1.828l1.936.645c.33.11.33.576 0 .686l-1.937.645a2.89 2.89 0 0 0-1.828 1.829l-.645 1.936a.361.361 0 0 1-.686 0l-.645-1.937a2.89 2.89 0 0 0-1.828-1.828l-1.937-.645a.361.361 0 0 1 0-.686l1.937-.645a2.89 2.89 0 0 0 1.828-1.828l.645-1.937zM3.794 1.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387A1.734 1.734 0 0 0 4.593 5.69l-.387 1.162a.217.217 0 0 1-.412 0L3.407 5.69A1.734 1.734 0 0 0 2.31 4.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387A1.734 1.734 0 0 0 3.407 2.31l.387-1.162zM10.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732L9.1 2.137a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L10.863.1z"/>
|
||||||
|
</svg>
|
||||||
|
<h4 class="fw-light">Free of Charge</h4>
|
||||||
|
<p class="w-75 m-auto fw-light">This service is free of charge. If you want to support us, just contact us.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr class="m-auto text-muted">
|
||||||
|
<div class="foot">
|
||||||
|
MORE TEXT
|
||||||
|
</div>
|
||||||
|
<span class="image-by">Image by <a class="text-decoration-none text-info" href="https://unsplash.com/photos/6ou8gWpS9ns"
|
||||||
|
target="_blank">Fredrick Tendong</a></span>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {onMounted} from "vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Home',
|
||||||
|
setup() {
|
||||||
|
onMounted(() => {
|
||||||
|
document.title = 'Home | CSGO-W.TV'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.main-content {
|
||||||
|
.head {
|
||||||
|
background-image: url("https://images.unsplash.com/photo-1560419015-7c427e8ae5ba?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1470&q=80");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
|
||||||
|
padding-top: 10rem;
|
||||||
|
padding-bottom: 10rem;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 5rem;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: 'CSGO';
|
||||||
|
position: absolute;
|
||||||
|
text-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-up {
|
||||||
|
font-size: 40%;
|
||||||
|
vertical-align: top;
|
||||||
|
text-shadow: 10px -5px 1rem rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
font-weight: lighter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.body, hr {
|
||||||
|
width: 65%;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: .9rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.foot {
|
||||||
|
margin-top: 5rem;
|
||||||
|
padding-bottom: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-by {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -35px;
|
||||||
|
right: 2rem;
|
||||||
|
font-size: .8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
177
src/views/Match.vue
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
<template>
|
||||||
|
<div class="pt-3">
|
||||||
|
<p class="text-center fs-6">Average Rank: <img :src="require('@/images/ranks/' + data.avgRank + '.png')"
|
||||||
|
alt="Rank icon"
|
||||||
|
class="rank-icon mx-2"/></p>
|
||||||
|
<div v-if="data.matchDetails" class="head row m-auto mb-3 text-center">
|
||||||
|
<div class="m-auto">
|
||||||
|
<img :alt="data.matchDetails.map"
|
||||||
|
:src="mapImg.includes(data.matchDetails.map) ? require('@/images/maps/' + data.matchDetails.map + '.png') : require('@/images/maps/not_found.png')"
|
||||||
|
:title="data.matchDetails.map" class="map-icon">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="nav">
|
||||||
|
<ul class="list-unstyled d-flex m-auto">
|
||||||
|
<li class="list-item active">Scoreboard</li>
|
||||||
|
<li class="list-item">Rounds</li>
|
||||||
|
<li class="list-item">Weapons</li>
|
||||||
|
<li class="list-item">Duels</li>
|
||||||
|
<li class="list-item">Heatmaps</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="container row m-auto">
|
||||||
|
<div class="score col-3 flex-column">
|
||||||
|
{{data.score[0]}}
|
||||||
|
-
|
||||||
|
{{data.score[1]}}
|
||||||
|
</div>
|
||||||
|
<div v-if="data.score.length === 2 && data.stats" class="col-9 d-flex flex-column">
|
||||||
|
<ScoreTeam :rounds_played="data.score.reduce((a, b) => a + b)" :stats="data.stats" :team_id="1"/>
|
||||||
|
<ScoreTeam :rounds_played="data.score.reduce((a, b) => a + b)" :stats="data.stats" :team_id="2"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {defineAsyncComponent, onBeforeMount, reactive, watch} from "vue";
|
||||||
|
import axios from 'axios'
|
||||||
|
import {GetHLTV_1, GoToPlayer} from "../utils";
|
||||||
|
import "../components/ScoreTeam"
|
||||||
|
|
||||||
|
const ScoreTeam = defineAsyncComponent(() => import('../components/ScoreTeam'))
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Match',
|
||||||
|
props: ['match_id'],
|
||||||
|
components: {ScoreTeam},
|
||||||
|
setup(props) {
|
||||||
|
// Vars
|
||||||
|
const mapImg = ['de_inferno', 'de_mirage', 'de_overpass']
|
||||||
|
|
||||||
|
// Refs
|
||||||
|
const data = reactive({
|
||||||
|
playerName: '',
|
||||||
|
matchDetails: {},
|
||||||
|
stats: [],
|
||||||
|
score: [0],
|
||||||
|
avgRank: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
const GetMatch = () => {
|
||||||
|
axios
|
||||||
|
.get(`http://localhost:1337/http://localhost:8000/match/${props.match_id}`)
|
||||||
|
.then((response) => {
|
||||||
|
document.title = `${response.data.map} | CSGO-W.TF`
|
||||||
|
data.matchDetails = response.data
|
||||||
|
data.stats = response.data.stats
|
||||||
|
data.score = response.data.score
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(e)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetAvgRank = () => {
|
||||||
|
let count = 0
|
||||||
|
let fullRank = 0
|
||||||
|
|
||||||
|
data.stats?.map(player => {
|
||||||
|
if (player.extended?.rank?.old) {
|
||||||
|
fullRank += player.extended?.rank?.old
|
||||||
|
count += 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (count === 0)
|
||||||
|
data.avgRank = 0
|
||||||
|
else
|
||||||
|
data.avgRank = Math.floor(fullRank / count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watchers
|
||||||
|
watch(() => props.match_id, GetMatch)
|
||||||
|
watch(() => data.stats, GetAvgRank)
|
||||||
|
|
||||||
|
// Run on create
|
||||||
|
onBeforeMount(() => {
|
||||||
|
GetMatch()
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
GetMatch, GetAvgRank, data, mapImg, GoToPlayer, GetHLTV_1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.rank-icon {
|
||||||
|
max-width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-icon {
|
||||||
|
max-width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.score {
|
||||||
|
font-size: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 900px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
tr {
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cursor__help {
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player__avatar {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player__name {
|
||||||
|
text-align: left;
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player__rank {
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player__rating {
|
||||||
|
border-radius: 25% 25%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
width: 100vw;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
|
||||||
|
.list-item {
|
||||||
|
padding: 10px 10px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--bs-info);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
background: var(--bs-info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
12
src/views/MyMatches.vue
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<table class="matches-table">
|
||||||
|
MyMatches
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default{
|
||||||
|
name: "MyMatches",
|
||||||
|
}
|
||||||
|
</script>
|
317
src/views/Player.vue
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wrapper">
|
||||||
|
<div class="container">
|
||||||
|
<div class="card mb-3 bg-transparent border-0" style="max-width: 540px;">
|
||||||
|
<div class="row g-0">
|
||||||
|
<div class="img-container col-md-4 pt-3">
|
||||||
|
<img
|
||||||
|
:src="data.playerDetails.avatar" alt="Player avatar" class="img-fluid avatar">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title"><a
|
||||||
|
:href="/^\d{17}$/.test(props.id) ? 'https://steamcommunity.com/profiles/' + props.id : 'https://steamcommunity.com/id/' + props.id"
|
||||||
|
class="text-decoration-none text-white"
|
||||||
|
target="_blank"
|
||||||
|
title="Open steam profile">{{
|
||||||
|
data.playerDetails.name
|
||||||
|
}}
|
||||||
|
<svg class="bi bi-link-45deg" fill="currentColor" height="16" viewBox="0 0 16 16"
|
||||||
|
width="16" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M4.715 6.542 3.343 7.914a3 3 0 1 0 4.243 4.243l1.828-1.829A3 3 0 0 0 8.586 5.5L8 6.086a1.002 1.002 0 0 0-.154.199 2 2 0 0 1 .861 3.337L6.88 11.45a2 2 0 1 1-2.83-2.83l.793-.792a4.018 4.018 0 0 1-.128-1.287z"/>
|
||||||
|
<path
|
||||||
|
d="M6.586 4.672A3 3 0 0 0 7.414 9.5l.775-.776a2 2 0 0 1-.896-3.346L9.12 3.55a2 2 0 1 1 2.83 2.83l-.793.792c.112.42.155.855.128 1.287l1.372-1.372a3 3 0 1 0-4.243-4.243L6.586 4.672z"/>
|
||||||
|
</svg>
|
||||||
|
</a></h3>
|
||||||
|
<table class="table table-borderless">
|
||||||
|
<tr>
|
||||||
|
<th class="text-uppercase text-muted">Wins</th>
|
||||||
|
<th class="text-uppercase text-muted">Losses</th>
|
||||||
|
<th class="text-uppercase text-muted">WinRate</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ wl.win }}</td>
|
||||||
|
<td>{{ wl.loss }}</td>
|
||||||
|
<td>{{ (wl.win / wl.loss * 100).toFixed(2) }}%</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<small v-if="data.playerDetails.tracked" class="card-text text-muted">
|
||||||
|
Currently tracked
|
||||||
|
</small>
|
||||||
|
<div v-else class="dropdown">
|
||||||
|
<button
|
||||||
|
id="login-dropdown"
|
||||||
|
aria-expanded="false"
|
||||||
|
class="btn border-2 btn-outline-info"
|
||||||
|
data-bs-toggle="dropdown"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Track Me!
|
||||||
|
</button>
|
||||||
|
<div aria-labelledby="login-dropdown" class="dropdown-menu mt-2 border-2 border-primary bg-body"
|
||||||
|
style="width: 320px">
|
||||||
|
<form class="px-4 py-3">
|
||||||
|
<!-- AuthCode input -->
|
||||||
|
<div class="form-outline mb-4">
|
||||||
|
<input id="track-authcode" v-model="data.userData.authcode" class="form-control bg-secondary"
|
||||||
|
placeholder="AuthCode*"
|
||||||
|
required type="text"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ShareCode input -->
|
||||||
|
<div class="form-outline mb-2">
|
||||||
|
<input id="track-sharecode" v-model="data.userData.sharecode" class="form-control bg-secondary"
|
||||||
|
placeholder="ShareCode"
|
||||||
|
type="text"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-outline mb-4">
|
||||||
|
<small>You can find your AuthCode and ShareCode <a
|
||||||
|
href="https://help.steampowered.com/en/wizard/HelpWithGameIssue/?appid=730&issueid=128" target="_blank">here</a>.</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Submit button -->
|
||||||
|
<button class="btn btn-outline-warning border-2" type="submit" @click.prevent="TrackMe">
|
||||||
|
TrackMe
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="matches m-auto">
|
||||||
|
<table v-if="data.matches" class="table table-borderless">
|
||||||
|
<thead class="border-bottom">
|
||||||
|
<tr>
|
||||||
|
<th class="text-center" scope="col">Map</th>
|
||||||
|
<th class="text-center" scope="col">Rank</th>
|
||||||
|
<th class="text-center" scope="col">Score</th>
|
||||||
|
<th class="text-center" scope="col">K</th>
|
||||||
|
<th class="text-center" scope="col">A</th>
|
||||||
|
<th class="text-center" scope="col">D</th>
|
||||||
|
<th class="text-center" scope="col" style="cursor: help" title="Kill-to-death ratio">+/-</th>
|
||||||
|
<th class="text-center" scope="col" style="cursor: help" title="Average damage per round">ADR</th>
|
||||||
|
<th class="text-center" scope="col" style="cursor: help" title="HLTV 1.0 Rating">Rating</th>
|
||||||
|
<th class="text-center" scope="col">Duration</th>
|
||||||
|
<th scope="col">Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="match in data.matches"
|
||||||
|
:key="match.match_id"
|
||||||
|
class="match"
|
||||||
|
@click="GoToMatch(match.match_id)">
|
||||||
|
<td class="td-map text-center">
|
||||||
|
<img :alt="match.map ? match.map : 'Map not found'"
|
||||||
|
:src="mapImg.includes(match.map) ? require('@/images/maps/' + match.map + '.png') : require('@/images/maps/not_found.png')"
|
||||||
|
:title="match.map"
|
||||||
|
class="map-icon">
|
||||||
|
</td>
|
||||||
|
<td class="td-rank text-center">
|
||||||
|
<img
|
||||||
|
:src="match.stats[0].extended?.rank?.new ? require('@/images/ranks/' + match.stats[0].extended?.rank?.new + '.png') : require('@/images/ranks/0.png')"
|
||||||
|
alt="Rank icon"
|
||||||
|
class="rank-icon">
|
||||||
|
</td>
|
||||||
|
<td :class="match.stats[0].team_id === match.match_result ? 'text-success' : !match.match_result ? 'text-warning' : 'text-danger'"
|
||||||
|
class="td-score text-center fw-bold">
|
||||||
|
{{ match.score[0] }} - {{ match.score[1] }}
|
||||||
|
</td>
|
||||||
|
<td class="td-kills text-center">
|
||||||
|
{{ match.stats[0].kills ? match.stats[0].kills : "0" }}
|
||||||
|
</td>
|
||||||
|
<td class="td-assists text-center">
|
||||||
|
{{ match.stats[0].assists ? match.stats[0].assists : "0" }}
|
||||||
|
</td>
|
||||||
|
<td class="td-deaths text-center">
|
||||||
|
{{ match.stats[0].deaths ? match.stats[0].deaths : "0" }}
|
||||||
|
</td>
|
||||||
|
<td :class="(match.stats[0].kills ? match.stats[0].kills : 0) - (match.stats[0].deaths ? match.stats[0].deaths : 0) >= 0 ? 'text-success' : 'text-danger'"
|
||||||
|
class="td-plus text-center">
|
||||||
|
{{
|
||||||
|
(match.stats[0].kills ? match.stats[0].kills : 0) - (match.stats[0].deaths ? match.stats[0].deaths : 0)
|
||||||
|
}}
|
||||||
|
</td>
|
||||||
|
<td class="td-adr text-center">
|
||||||
|
{{
|
||||||
|
Math.floor((match.stats[0].extended.dmg.total ? match.stats[0].extended.dmg.total : 0) / (match.score[0] + match.score[1]))
|
||||||
|
}}
|
||||||
|
</td>
|
||||||
|
<td :class="GetHLTV_1(
|
||||||
|
match.stats[0].kills,
|
||||||
|
match.score[0] + match.score[1],
|
||||||
|
match.stats[0].deaths,
|
||||||
|
match.stats[0].extended?.multi_kills?.duo,
|
||||||
|
match.stats[0].extended?.multi_kills?.triple,
|
||||||
|
match.stats[0].extended?.multi_kills?.quad,
|
||||||
|
match.stats[0].extended?.multi_kills?.pent) >= 1 ? 'text-success' : 'text-warning'"
|
||||||
|
class="td-hltv text-center fw-bold">
|
||||||
|
{{
|
||||||
|
GetHLTV_1(
|
||||||
|
match.stats[0].kills,
|
||||||
|
match.score[0] + match.score[1],
|
||||||
|
match.stats[0].deaths,
|
||||||
|
match.stats[0].extended?.multi_kills?.duo,
|
||||||
|
match.stats[0].extended?.multi_kills?.triple,
|
||||||
|
match.stats[0].extended?.multi_kills?.quad,
|
||||||
|
match.stats[0].extended?.multi_kills?.pent)
|
||||||
|
}}
|
||||||
|
</td>
|
||||||
|
<td class="td-duration text-center">
|
||||||
|
{{ FormatDuration(match.duration) }}
|
||||||
|
</td>
|
||||||
|
<td class="td-date">
|
||||||
|
{{ FormatDate(match.date) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h5 v-else>No matches on record</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {onBeforeMount, reactive, watch} from "vue";
|
||||||
|
import axios from "axios";
|
||||||
|
import {useStore} from "vuex";
|
||||||
|
import {FormatDate, FormatDuration, GetHLTV_1, GoToMatch} from "@/utils";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Player',
|
||||||
|
props: ['id'],
|
||||||
|
setup(props) {
|
||||||
|
const store = useStore()
|
||||||
|
|
||||||
|
// Vars
|
||||||
|
const mapImg = ['de_inferno', 'de_mirage', 'de_overpass']
|
||||||
|
|
||||||
|
const wl = reactive({
|
||||||
|
win: 132,
|
||||||
|
loss: 102
|
||||||
|
})
|
||||||
|
|
||||||
|
const data = reactive({
|
||||||
|
userData: {
|
||||||
|
authcode: '',
|
||||||
|
sharecode: ''
|
||||||
|
},
|
||||||
|
playerDetails: {},
|
||||||
|
matches: [],
|
||||||
|
statusError: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
const TrackMe = async () => {
|
||||||
|
const shareCodeRegex = /^CSGO(?:-?[ABCDEFGHJKLMNOPQRSTUVWXYZabcdefhijkmnopqrstuvwxyz23456789]{5}){5}$/
|
||||||
|
const authCodeRegex = /^[ABCDEFGHJKLMNOPQRSTUVWXYZ23456789]{4}-[ABCDEFGHJKLMNOPQRSTUVWXYZ23456789]{5}-[ABCDEFGHJKLMNOPQRSTUVWXYZ23456789]{4}$/
|
||||||
|
|
||||||
|
if (!shareCodeRegex.test(data.userData.sharecode))
|
||||||
|
data.statusError = 'Is not a valid sharecode'
|
||||||
|
if (!authCodeRegex.test(data.userData.authcode))
|
||||||
|
data.statusError = 'Is not a valid authcode'
|
||||||
|
|
||||||
|
const res = await axios
|
||||||
|
.post(`http://localhost:1337/http://localhost:8000/player/trackme`, `id=${store.state.id64}&authcode=${data.userData.authcode}&sharecode=${data.userData.sharecode}`)
|
||||||
|
|
||||||
|
if (res.status === 401) {
|
||||||
|
data.statusError = 'Data does not match player'
|
||||||
|
} else if (res.status === 400) {
|
||||||
|
data.statusError = 'Userinput was wrong'
|
||||||
|
} else if (res.status === 200) {
|
||||||
|
data.statusError = ''
|
||||||
|
} else {
|
||||||
|
console.log(`${res.status}: ${res.statusText}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetUser = () => {
|
||||||
|
axios
|
||||||
|
.get(`http://localhost:1337/http://localhost:8000/player/${props.id}`)
|
||||||
|
.then((response) => {
|
||||||
|
data.playerDetails = response.data
|
||||||
|
data.matches = response.data.matches
|
||||||
|
store.state.id64 = response.data.steamid64
|
||||||
|
|
||||||
|
console.log(response.data)
|
||||||
|
document.title = `${response.data.name} | CSGO-W.TF`
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.id, GetUser)
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
GetUser()
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
data, store, mapImg, wl, props, GetUser, TrackMe, FormatDate, FormatDuration, GoToMatch, GetHLTV_1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.card {
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
th:last-child, td:last-child {
|
||||||
|
text-align: right;
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.td-map {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.td-rank {
|
||||||
|
width: 88px;
|
||||||
|
height: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.td-score {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
border-radius: 50%;
|
||||||
|
height: 150px;
|
||||||
|
width: 150px;
|
||||||
|
box-shadow: 0 0 10px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-icon {
|
||||||
|
height: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-icon {
|
||||||
|
height: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.match {
|
||||||
|
border-bottom: 1px solid rgba(73, 73, 73, 0.73);
|
||||||
|
}
|
||||||
|
|
||||||
|
.match:last-child {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.match:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background: rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
</style>
|