Add better player card details and ringers
							parent
							
								
									c08f2434e6
								
							
						
					
					
						commit
						849b628130
					
				| 
						 | 
					@ -9,7 +9,9 @@
 | 
				
			||||||
      "version": "0.0.0",
 | 
					      "version": "0.0.0",
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "axios": "^1.7.7",
 | 
					        "axios": "^1.7.7",
 | 
				
			||||||
 | 
					        "bootstrap-icons": "^1.11.3",
 | 
				
			||||||
        "pinia": "^2.2.4",
 | 
					        "pinia": "^2.2.4",
 | 
				
			||||||
 | 
					        "v-tooltip": "^2.1.3",
 | 
				
			||||||
        "vue": "^3.5.12",
 | 
					        "vue": "^3.5.12",
 | 
				
			||||||
        "vue-router": "^4.4.5"
 | 
					        "vue-router": "^4.4.5"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
| 
						 | 
					@ -68,6 +70,18 @@
 | 
				
			||||||
        "node": ">=6.0.0"
 | 
					        "node": ">=6.0.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/@babel/runtime": {
 | 
				
			||||||
 | 
					      "version": "7.25.9",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.9.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-4zpTHZ9Cm6L9L+uIqghQX8ZXg8HKFcjYO3qHoO8zTmRm6HQUJ8SSJ+KRvbMBZn0EGVlT4DRYeQ/6hjlyXBh+Kg==",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "regenerator-runtime": "^0.14.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=6.9.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/@babel/types": {
 | 
					    "node_modules/@babel/types": {
 | 
				
			||||||
      "version": "7.25.9",
 | 
					      "version": "7.25.9",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz",
 | 
				
			||||||
| 
						 | 
					@ -2064,6 +2078,22 @@
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "license": "ISC"
 | 
					      "license": "ISC"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/bootstrap-icons": {
 | 
				
			||||||
 | 
					      "version": "1.11.3",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww==",
 | 
				
			||||||
 | 
					      "funding": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "type": "github",
 | 
				
			||||||
 | 
					          "url": "https://github.com/sponsors/twbs"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "type": "opencollective",
 | 
				
			||||||
 | 
					          "url": "https://opencollective.com/bootstrap"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      "license": "MIT"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/brace-expansion": {
 | 
					    "node_modules/brace-expansion": {
 | 
				
			||||||
      "version": "2.0.1",
 | 
					      "version": "2.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
 | 
				
			||||||
| 
						 | 
					@ -4442,7 +4472,6 @@
 | 
				
			||||||
      "version": "4.17.21",
 | 
					      "version": "4.17.21",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
 | 
				
			||||||
      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
 | 
					      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "license": "MIT"
 | 
					      "license": "MIT"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/lodash.merge": {
 | 
					    "node_modules/lodash.merge": {
 | 
				
			||||||
| 
						 | 
					@ -5171,6 +5200,17 @@
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "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",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "funding": {
 | 
				
			||||||
 | 
					        "type": "opencollective",
 | 
				
			||||||
 | 
					        "url": "https://opencollective.com/popperjs"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/postcss": {
 | 
					    "node_modules/postcss": {
 | 
				
			||||||
      "version": "8.4.47",
 | 
					      "version": "8.4.47",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
 | 
				
			||||||
| 
						 | 
					@ -5374,6 +5414,12 @@
 | 
				
			||||||
        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
 | 
					        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/regenerator-runtime": {
 | 
				
			||||||
 | 
					      "version": "0.14.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
 | 
				
			||||||
 | 
					      "license": "MIT"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/request-progress": {
 | 
					    "node_modules/request-progress": {
 | 
				
			||||||
      "version": "3.0.0",
 | 
					      "version": "3.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz",
 | 
				
			||||||
| 
						 | 
					@ -5676,6 +5722,16 @@
 | 
				
			||||||
        "node": ">=8"
 | 
					        "node": ">=8"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/source-map": {
 | 
				
			||||||
 | 
					      "version": "0.6.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
 | 
				
			||||||
 | 
					      "license": "BSD-3-Clause",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.10.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/source-map-js": {
 | 
					    "node_modules/source-map-js": {
 | 
				
			||||||
      "version": "1.2.1",
 | 
					      "version": "1.2.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
 | 
				
			||||||
| 
						 | 
					@ -6195,6 +6251,73 @@
 | 
				
			||||||
        "uuid": "dist/bin/uuid"
 | 
					        "uuid": "dist/bin/uuid"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/v-tooltip": {
 | 
				
			||||||
 | 
					      "version": "2.1.3",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/v-tooltip/-/v-tooltip-2.1.3.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-xXngyxLQTOx/yUEy50thb8te7Qo4XU6h4LZB6cvEfVd9mnysUxLEoYwGWDdqR+l69liKsy3IPkdYff3J1gAJ5w==",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "@babel/runtime": "^7.13.10",
 | 
				
			||||||
 | 
					        "lodash": "^4.17.21",
 | 
				
			||||||
 | 
					        "popper.js": "^1.16.1",
 | 
				
			||||||
 | 
					        "vue-resize": "^1.0.1"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/v-tooltip/node_modules/@vue/compiler-sfc": {
 | 
				
			||||||
 | 
					      "version": "2.7.16",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "@babel/parser": "^7.23.5",
 | 
				
			||||||
 | 
					        "postcss": "^8.4.14",
 | 
				
			||||||
 | 
					        "source-map": "^0.6.1"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "optionalDependencies": {
 | 
				
			||||||
 | 
					        "prettier": "^1.18.2 || ^2.0.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/v-tooltip/node_modules/prettier": {
 | 
				
			||||||
 | 
					      "version": "2.8.8",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "bin": {
 | 
				
			||||||
 | 
					        "prettier": "bin-prettier.js"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=10.13.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "funding": {
 | 
				
			||||||
 | 
					        "url": "https://github.com/prettier/prettier?sponsor=1"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/v-tooltip/node_modules/vue": {
 | 
				
			||||||
 | 
					      "version": "2.7.16",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==",
 | 
				
			||||||
 | 
					      "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "@vue/compiler-sfc": "2.7.16",
 | 
				
			||||||
 | 
					        "csstype": "^3.1.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/v-tooltip/node_modules/vue-resize": {
 | 
				
			||||||
 | 
					      "version": "1.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-1.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-z5M7lJs0QluJnaoMFTIeGx6dIkYxOwHThlZDeQnWZBizKblb99GSejPnK37ZbNE/rVwDcYcHY+Io+AxdpY952w==",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "@babel/runtime": "^7.13.10"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "peerDependencies": {
 | 
				
			||||||
 | 
					        "vue": "^2.6.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/verror": {
 | 
					    "node_modules/verror": {
 | 
				
			||||||
      "version": "1.10.0",
 | 
					      "version": "1.10.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,9 @@
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "axios": "^1.7.7",
 | 
					    "axios": "^1.7.7",
 | 
				
			||||||
 | 
					    "bootstrap-icons": "^1.11.3",
 | 
				
			||||||
    "pinia": "^2.2.4",
 | 
					    "pinia": "^2.2.4",
 | 
				
			||||||
 | 
					    "v-tooltip": "^2.1.3",
 | 
				
			||||||
    "vue": "^3.5.12",
 | 
					    "vue": "^3.5.12",
 | 
				
			||||||
    "vue-router": "^4.4.5"
 | 
					    "vue-router": "^4.4.5"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,6 @@
 | 
				
			||||||
 | 
					@import url("tf2icons.css");
 | 
				
			||||||
 | 
					@import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* color palette from <https://github.com/vuejs/theme> */
 | 
					/* color palette from <https://github.com/vuejs/theme> */
 | 
				
			||||||
:root {
 | 
					:root {
 | 
				
			||||||
  --vt-c-white: #ffffff;
 | 
					  --vt-c-white: #ffffff;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
											
												Binary file not shown.
											
										
									
								
											
												
													File diff suppressed because one or more lines are too long
												
											
										
									
								| 
		 After Width: | Height: | Size: 93 KiB  | 
											
												Binary file not shown.
											
										
									
								
											
												Binary file not shown.
											
										
									
								| 
						 | 
					@ -23,12 +23,26 @@ a,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
button {
 | 
					button {
 | 
				
			||||||
    color: var(--text);
 | 
					  font-weight: 700;
 | 
				
			||||||
    border: none;
 | 
					  color: var(--text);
 | 
				
			||||||
 | 
					  background-color: var(--surface-0);
 | 
				
			||||||
 | 
					  border: none;
 | 
				
			||||||
 | 
					  padding: 8px;
 | 
				
			||||||
 | 
					  border-radius: 4px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					button.accent {
 | 
				
			||||||
 | 
					  background-color: var(--accent);
 | 
				
			||||||
 | 
					  color: var(--base);
 | 
				
			||||||
 | 
					  text-transform: uppercase;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
h1 {
 | 
					h1 {
 | 
				
			||||||
  font-weight: 800;
 | 
					  font-weight: 800;
 | 
				
			||||||
  font-size: 300%;
 | 
					  font-size: 200%;
 | 
				
			||||||
 | 
					  line-height: 2em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					em.aside {
 | 
				
			||||||
 | 
					  color: var(--overlay-0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,75 @@
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-family: 'tf2-classicons';
 | 
				
			||||||
 | 
					  src:  url('fonts/tf2-classicons.eot?bv99da');
 | 
				
			||||||
 | 
					  src:  url('fonts/tf2-classicons.eot?bv99da#iefix') format('embedded-opentype'),
 | 
				
			||||||
 | 
					    url('fonts/tf2-classicons.ttf?bv99da') format('truetype'),
 | 
				
			||||||
 | 
					    url('fonts/tf2-classicons.woff?bv99da') format('woff'),
 | 
				
			||||||
 | 
					    url('fonts/tf2-classicons.svg?bv99da#tf2-classicons') format('svg');
 | 
				
			||||||
 | 
					  font-weight: normal;
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i, .icomoon-liga {
 | 
				
			||||||
 | 
					  /* use !important to prevent issues with browser extensions that change fonts */
 | 
				
			||||||
 | 
					  font-family: 'tf2-classicons' !important;
 | 
				
			||||||
 | 
					  speak: none;
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: normal;
 | 
				
			||||||
 | 
					  font-variant: normal;
 | 
				
			||||||
 | 
					  text-transform: none;
 | 
				
			||||||
 | 
					  line-height: 1;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Enable Ligatures ================ */
 | 
				
			||||||
 | 
					  letter-spacing: 0;
 | 
				
			||||||
 | 
					  -webkit-font-feature-settings: "liga";
 | 
				
			||||||
 | 
					  -moz-font-feature-settings: "liga=1";
 | 
				
			||||||
 | 
					  -moz-font-feature-settings: "liga";
 | 
				
			||||||
 | 
					  -ms-font-feature-settings: "liga" 1;
 | 
				
			||||||
 | 
					  font-feature-settings: "liga";
 | 
				
			||||||
 | 
					  -webkit-font-variant-ligatures: discretionary-ligatures;
 | 
				
			||||||
 | 
					  font-variant-ligatures: discretionary-ligatures;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Better Font Rendering =========== */
 | 
				
			||||||
 | 
					  -webkit-font-smoothing: antialiased;
 | 
				
			||||||
 | 
					  -moz-osx-font-smoothing: grayscale;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.tf2-Heavy:before {
 | 
				
			||||||
 | 
					  content: "\1f4aa";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.tf2-Medic:before {
 | 
				
			||||||
 | 
					  content: "\1f497";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.tf2-Pyro:before {
 | 
				
			||||||
 | 
					  content: "\1f525";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.tf2-Scout:before {
 | 
				
			||||||
 | 
					  content: "\1f407";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.tf2-Sniper:before {
 | 
				
			||||||
 | 
					  content: "\1f3b7";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.tf2-Soldier:before {
 | 
				
			||||||
 | 
					  content: "\1f4a5";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.tf2-Spy:before {
 | 
				
			||||||
 | 
					  content: "\1f4e6";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.tf2-Demo:before {
 | 
				
			||||||
 | 
					  content: "\1f4a3";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.tf2-Engineer:before {
 | 
				
			||||||
 | 
					  content: "\1f527";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.tf2-FlankSoldier:before {
 | 
				
			||||||
 | 
					  content: "\1f400";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.tf2-PocketSoldier:before {
 | 
				
			||||||
 | 
					  content: "\1f418";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.tf2-FlankScout:before {
 | 
				
			||||||
 | 
					  content: "\1f43f";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.tf2-PocketScout:before {
 | 
				
			||||||
 | 
					  content: "\1f416";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -9,21 +9,47 @@ const props = defineProps({
 | 
				
			||||||
  roleTitle: String,
 | 
					  roleTitle: String,
 | 
				
			||||||
  player: Object as PropType<PlayerTeamRole>,
 | 
					  player: Object as PropType<PlayerTeamRole>,
 | 
				
			||||||
  isRoster: Boolean,
 | 
					  isRoster: Boolean,
 | 
				
			||||||
 | 
					  isRinger: Boolean,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const isSelected = computed(() => {
 | 
					const isSelected = computed(() => {
 | 
				
			||||||
  if (props.isRoster) {
 | 
					  if (props.isRoster) {
 | 
				
			||||||
    return rosterStore.selectedRole == props.roleTitle;
 | 
					    return rosterStore.selectedRole == props.roleTitle;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (props.isRinger) {
 | 
				
			||||||
 | 
					    return rosterStore.selectedPlayers[props.roleTitle]?.playtime == -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return Object.values(rosterStore.selectedPlayers).includes(props.player);
 | 
					  return Object.values(rosterStore.selectedPlayers).includes(props.player);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function onClick() {
 | 
					function onClick() {
 | 
				
			||||||
  if (props.isRoster) {
 | 
					  if (props.isRoster) {
 | 
				
			||||||
    rosterStore.selectedRole = props.roleTitle;
 | 
					    if (rosterStore.selectedRole == props.roleTitle) {
 | 
				
			||||||
 | 
					      rosterStore.selectedRole = undefined;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      rosterStore.selectedRole = props.roleTitle;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    // we are selecting the player
 | 
					    // we are selecting the player
 | 
				
			||||||
    rosterStore.selectPlayerForRole(props.player, props.roleTitle);
 | 
					    if (isSelected.value) {
 | 
				
			||||||
 | 
					      rosterStore.selectPlayerForRole(undefined, props.roleTitle);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      if (props.isRinger) {
 | 
				
			||||||
 | 
					        const ringerPlayer: PlayerTeamRole = {
 | 
				
			||||||
 | 
					          steamId: -1,
 | 
				
			||||||
 | 
					          name: "Ringer",
 | 
				
			||||||
 | 
					          role: props.roleTitle,
 | 
				
			||||||
 | 
					          main: false,
 | 
				
			||||||
 | 
					          availability: 1,
 | 
				
			||||||
 | 
					          playtime: -1,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        rosterStore.selectPlayerForRole(ringerPlayer, props.roleTitle);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        rosterStore.selectPlayerForRole(props.player, props.roleTitle);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					@ -31,45 +57,81 @@ function onClick() {
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <button :class="{
 | 
					  <button :class="{
 | 
				
			||||||
    'player-card': true,
 | 
					    'player-card': true,
 | 
				
			||||||
    'no-player': !player,
 | 
					    'no-player': !player && !isRinger,
 | 
				
			||||||
    'selected': isSelected,
 | 
					    'selected': isSelected,
 | 
				
			||||||
    }" @click="onClick">
 | 
					    'can-be-available': player?.availability == 2
 | 
				
			||||||
    <div v-if="player">
 | 
					  }" @click="onClick">
 | 
				
			||||||
      <h1>{{ player.name }}</h1>
 | 
					    <div class="role-icon">
 | 
				
			||||||
      <span v-if="roleTitle != player.role">
 | 
					      <i :class="rosterStore.roleIcons[roleTitle]" />
 | 
				
			||||||
        Subbing in as
 | 
					    </div>
 | 
				
			||||||
      </span>
 | 
					    <div v-if="player" class="role-info">
 | 
				
			||||||
      {{ player.role }}
 | 
					      <span>
 | 
				
			||||||
      <span v-if="!player.main">
 | 
					        <h4 class="player-name">{{ player.name }}</h4>
 | 
				
			||||||
        (alternate role)
 | 
					        <span v-if="roleTitle != player.role">
 | 
				
			||||||
 | 
					          Subbing in as
 | 
				
			||||||
 | 
					        </span>
 | 
				
			||||||
 | 
					        {{ player.role }}
 | 
				
			||||||
 | 
					        <span v-if="!player.main && isRoster">
 | 
				
			||||||
 | 
					          (alternate)
 | 
				
			||||||
 | 
					        </span>
 | 
				
			||||||
      </span>
 | 
					      </span>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div v-else>
 | 
					    <div v-else-if="isRinger" class="role-info">
 | 
				
			||||||
      {{ roleTitle }}
 | 
					      <span>
 | 
				
			||||||
 | 
					        <h4 class="player-name">Ringer</h4>
 | 
				
			||||||
 | 
					        {{ roleTitle }}
 | 
				
			||||||
 | 
					      </span>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div v-else class="role-info">
 | 
				
			||||||
 | 
					      <span>
 | 
				
			||||||
 | 
					        {{ roleTitle }}
 | 
				
			||||||
 | 
					      </span>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </button>
 | 
					  </button>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style scoped>
 | 
					<style scoped>
 | 
				
			||||||
.player-card {
 | 
					.player-card {
 | 
				
			||||||
  background-color: var(--crust);
 | 
					  background-color: white;
 | 
				
			||||||
  padding: 1em;
 | 
					  padding: 1em;
 | 
				
			||||||
  border-radius: 8px;
 | 
					  border-radius: 8px;
 | 
				
			||||||
  user-select: none;
 | 
					  user-select: none;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  gap: 1em;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  border: 2px solid white;
 | 
				
			||||||
 | 
					  box-shadow: 1px 1px 8px var(--surface-0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.player-card.can-be-available {
 | 
				
			||||||
 | 
					  color: var(--overlay-0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.player-card .role-icon {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: row;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  font-size: 2em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.player-card .role-info {
 | 
				
			||||||
 | 
					  text-align: left;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.player-card:hover {
 | 
					.player-card:hover {
 | 
				
			||||||
  background-color: var(--surface-0);
 | 
					  background-color: var(--surface-0);
 | 
				
			||||||
  transition-duration: 200ms;
 | 
					  transition-duration: 200ms;
 | 
				
			||||||
 | 
					  border-color: var(--surface-0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.player-card.no-player {
 | 
					.player-card.no-player {
 | 
				
			||||||
  border: 2px dashed var(--overlay-0);
 | 
					  border: 2px solid var(--overlay-0);
 | 
				
			||||||
 | 
					  box-shadow: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.player-card.no-player.selected {
 | 
					.player-card.no-player.selected {
 | 
				
			||||||
  background-color: var(--accent-transparent);
 | 
					  background-color: var(--accent-transparent);
 | 
				
			||||||
  border: 2px dashed var(--accent);
 | 
					  border: 2px solid var(--accent);
 | 
				
			||||||
  color: var(--accent);
 | 
					  color: var(--accent);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,8 +151,8 @@ function onClick() {
 | 
				
			||||||
  color: var(--accent);
 | 
					  color: var(--accent);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
h1 {
 | 
					.player-name {
 | 
				
			||||||
  font-size: 24px;
 | 
					  font-size: 16px;
 | 
				
			||||||
  font-weight: 700;
 | 
					  font-weight: 600;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,4 +9,5 @@ export interface PlayerTeamRole {
 | 
				
			||||||
  role: string;
 | 
					  role: string;
 | 
				
			||||||
  main: boolean;
 | 
					  main: boolean;
 | 
				
			||||||
  availability: number;
 | 
					  availability: number;
 | 
				
			||||||
 | 
					  playtime: number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ const router = createRouter({
 | 
				
			||||||
      path: "/schedule/roster",
 | 
					      path: "/schedule/roster",
 | 
				
			||||||
      name: "roster-builder",
 | 
					      name: "roster-builder",
 | 
				
			||||||
      component: RosterBuilderView
 | 
					      component: RosterBuilderView
 | 
				
			||||||
    }
 | 
					    },
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const selectedPlayers: Reactive<{ [key: string]: PlayerTeamRole }> = reactive({});
 | 
					  const selectedPlayers: Reactive<{ [key: string]: PlayerTeamRole }> = reactive({});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const selectedRole: Ref<String | undefined> = ref("Pocket Scout");
 | 
					  const selectedRole: Ref<String | undefined> = ref(undefined);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const availablePlayers: Reactive<Array<PlayerTeamRole>> = reactive([
 | 
					  const availablePlayers: Reactive<Array<PlayerTeamRole>> = reactive([
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Flank Scout",
 | 
					      role: "Flank Scout",
 | 
				
			||||||
      main: true,
 | 
					      main: true,
 | 
				
			||||||
      availability: 1,
 | 
					      availability: 1,
 | 
				
			||||||
 | 
					      playtime: 35031,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      steamId: 2839,
 | 
					      steamId: 2839,
 | 
				
			||||||
| 
						 | 
					@ -30,6 +31,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Flank Scout",
 | 
					      role: "Flank Scout",
 | 
				
			||||||
      main: false,
 | 
					      main: false,
 | 
				
			||||||
      availability: 1,
 | 
					      availability: 1,
 | 
				
			||||||
 | 
					      playtime: 28811,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      steamId: 2839,
 | 
					      steamId: 2839,
 | 
				
			||||||
| 
						 | 
					@ -37,6 +39,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Pocket Scout",
 | 
					      role: "Pocket Scout",
 | 
				
			||||||
      main: true,
 | 
					      main: true,
 | 
				
			||||||
      availability: 1,
 | 
					      availability: 1,
 | 
				
			||||||
 | 
					      playtime: 28811,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      steamId: 2841,
 | 
					      steamId: 2841,
 | 
				
			||||||
| 
						 | 
					@ -44,6 +47,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Pocket Soldier",
 | 
					      role: "Pocket Soldier",
 | 
				
			||||||
      main: true,
 | 
					      main: true,
 | 
				
			||||||
      availability: 2,
 | 
					      availability: 2,
 | 
				
			||||||
 | 
					      playtime: 98372,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      steamId: 2841,
 | 
					      steamId: 2841,
 | 
				
			||||||
| 
						 | 
					@ -51,6 +55,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Roamer",
 | 
					      role: "Roamer",
 | 
				
			||||||
      main: false,
 | 
					      main: false,
 | 
				
			||||||
      availability: 2,
 | 
					      availability: 2,
 | 
				
			||||||
 | 
					      playtime: 98372,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      steamId: 2282,
 | 
					      steamId: 2282,
 | 
				
			||||||
| 
						 | 
					@ -58,6 +63,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Demoman",
 | 
					      role: "Demoman",
 | 
				
			||||||
      main: true,
 | 
					      main: true,
 | 
				
			||||||
      availability: 2,
 | 
					      availability: 2,
 | 
				
			||||||
 | 
					      playtime: 47324,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      steamId: 2842,
 | 
					      steamId: 2842,
 | 
				
			||||||
| 
						 | 
					@ -65,6 +71,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Roamer",
 | 
					      role: "Roamer",
 | 
				
			||||||
      main: false,
 | 
					      main: false,
 | 
				
			||||||
      availability: 2,
 | 
					      availability: 2,
 | 
				
			||||||
 | 
					      playtime: 12028,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      steamId: 2842,
 | 
					      steamId: 2842,
 | 
				
			||||||
| 
						 | 
					@ -72,6 +79,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Demoman",
 | 
					      role: "Demoman",
 | 
				
			||||||
      main: false,
 | 
					      main: false,
 | 
				
			||||||
      availability: 2,
 | 
					      availability: 2,
 | 
				
			||||||
 | 
					      playtime: 12028,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      steamId: 2842,
 | 
					      steamId: 2842,
 | 
				
			||||||
| 
						 | 
					@ -79,6 +87,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Pocket Scout",
 | 
					      role: "Pocket Scout",
 | 
				
			||||||
      main: false,
 | 
					      main: false,
 | 
				
			||||||
      availability: 2,
 | 
					      availability: 2,
 | 
				
			||||||
 | 
					      playtime: 12028,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    //{
 | 
					    //{
 | 
				
			||||||
    //  steamId: 2843,
 | 
					    //  steamId: 2843,
 | 
				
			||||||
| 
						 | 
					@ -93,6 +102,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Pocket Soldier",
 | 
					      role: "Pocket Soldier",
 | 
				
			||||||
      main: false,
 | 
					      main: false,
 | 
				
			||||||
      availability: 2,
 | 
					      availability: 2,
 | 
				
			||||||
 | 
					      playtime: 50201,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      steamId: 2843,
 | 
					      steamId: 2843,
 | 
				
			||||||
| 
						 | 
					@ -100,6 +110,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Roamer",
 | 
					      role: "Roamer",
 | 
				
			||||||
      main: false,
 | 
					      main: false,
 | 
				
			||||||
      availability: 2,
 | 
					      availability: 2,
 | 
				
			||||||
 | 
					      playtime: 50201,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      steamId: 2844,
 | 
					      steamId: 2844,
 | 
				
			||||||
| 
						 | 
					@ -107,6 +118,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Roamer",
 | 
					      role: "Roamer",
 | 
				
			||||||
      main: true,
 | 
					      main: true,
 | 
				
			||||||
      availability: 1,
 | 
					      availability: 1,
 | 
				
			||||||
 | 
					      playtime: 4732,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      steamId: 2844,
 | 
					      steamId: 2844,
 | 
				
			||||||
| 
						 | 
					@ -114,6 +126,7 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
      role: "Pocket Soldier",
 | 
					      role: "Pocket Soldier",
 | 
				
			||||||
      main: false,
 | 
					      main: false,
 | 
				
			||||||
      availability: 1,
 | 
					      availability: 1,
 | 
				
			||||||
 | 
					      playtime: 4732,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  ]);
 | 
					  ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,9 +142,27 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
    return availablePlayerRoles.value.filter((player) => player.availability == 1);
 | 
					    return availablePlayerRoles.value.filter((player) => player.availability == 1);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const mainRoles = computed(() => {
 | 
				
			||||||
 | 
					    return availablePlayerRoles.value.filter((player) => player.main)
 | 
				
			||||||
 | 
					      .sort((a, b) => b.playtime - a.playtime);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const alternateRoles = computed(() => {
 | 
				
			||||||
 | 
					    return availablePlayerRoles.value.filter((player) => !player.main)
 | 
				
			||||||
 | 
					      .sort((a, b) => b.playtime - a.playtime);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const roleIcons = reactive({
 | 
				
			||||||
 | 
					    "Pocket Scout": "tf2-PocketScout",
 | 
				
			||||||
 | 
					    "Flank Scout": "tf2-FlankScout",
 | 
				
			||||||
 | 
					    "Pocket Soldier": "tf2-PocketSoldier",
 | 
				
			||||||
 | 
					    "Roamer": "tf2-FlankSoldier",
 | 
				
			||||||
 | 
					    "Demoman": "tf2-Demo",
 | 
				
			||||||
 | 
					    "Medic": "tf2-Medic",
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function selectPlayerForRole(player: PlayerTeamRole, role: string) {
 | 
					  function selectPlayerForRole(player: PlayerTeamRole, role: string) {
 | 
				
			||||||
    console.log("selecting.");
 | 
					    if (player && player.steamId > 0) {
 | 
				
			||||||
    if (player) {
 | 
					 | 
				
			||||||
      const existingRole = Object.keys(selectedPlayers).find((selectedRole) => {
 | 
					      const existingRole = Object.keys(selectedPlayers).find((selectedRole) => {
 | 
				
			||||||
        return selectedPlayers[selectedRole]?.steamId == player.steamId &&
 | 
					        return selectedPlayers[selectedRole]?.steamId == player.steamId &&
 | 
				
			||||||
          role != selectedRole;
 | 
					          role != selectedRole;
 | 
				
			||||||
| 
						 | 
					@ -154,5 +185,8 @@ export const useRosterStore = defineStore("roster", () => {
 | 
				
			||||||
    selectPlayerForRole,
 | 
					    selectPlayerForRole,
 | 
				
			||||||
    definitelyAvailable,
 | 
					    definitelyAvailable,
 | 
				
			||||||
    canBeAvailable,
 | 
					    canBeAvailable,
 | 
				
			||||||
 | 
					    roleIcons,
 | 
				
			||||||
 | 
					    mainRoles,
 | 
				
			||||||
 | 
					    alternateRoles,
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,11 +10,27 @@ const rosterStore = useRosterStore();
 | 
				
			||||||
const hasAvailablePlayers = computed(() => {
 | 
					const hasAvailablePlayers = computed(() => {
 | 
				
			||||||
  return rosterStore.availablePlayerRoles.length > 0;
 | 
					  return rosterStore.availablePlayerRoles.length > 0;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const hasAlternates = computed(() => {
 | 
				
			||||||
 | 
					  return rosterStore.alternateRoles.length > 0;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <main>
 | 
					  <main>
 | 
				
			||||||
    <h1>Roster</h1>
 | 
					    <div class="top">
 | 
				
			||||||
 | 
					      <h1 class="roster-title">
 | 
				
			||||||
 | 
					        Roster for Snus Brotherhood
 | 
				
			||||||
 | 
					        <em class="aside date">Aug. 13, 2036 @ 11:30 PM EST</em>
 | 
				
			||||||
 | 
					      </h1>
 | 
				
			||||||
 | 
					      <div class="button-group">
 | 
				
			||||||
 | 
					        <button>
 | 
				
			||||||
 | 
					          <i class="bi bi-box-arrow-left"></i>
 | 
				
			||||||
 | 
					          Back
 | 
				
			||||||
 | 
					        </button>
 | 
				
			||||||
 | 
					        <button class="accent">Submit</button>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
    <div class="columns">
 | 
					    <div class="columns">
 | 
				
			||||||
      <div class="column">
 | 
					      <div class="column">
 | 
				
			||||||
        <PlayerCard v-for="role in rosterStore.neededRoles"
 | 
					        <PlayerCard v-for="role in rosterStore.neededRoles"
 | 
				
			||||||
| 
						 | 
					@ -23,25 +39,38 @@ const hasAvailablePlayers = computed(() => {
 | 
				
			||||||
                    is-roster />
 | 
					                    is-roster />
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <div class="column">
 | 
					      <div class="column">
 | 
				
			||||||
        <h3 v-if="hasAvailablePlayers">Available</h3>
 | 
					        <PlayerCard v-for="player in rosterStore.mainRoles"
 | 
				
			||||||
        <PlayerCard v-for="player in rosterStore.definitelyAvailable"
 | 
					 | 
				
			||||||
                    :player="player"
 | 
					                    :player="player"
 | 
				
			||||||
                    :role-title="player.role" />
 | 
					                    :role-title="player.role" />
 | 
				
			||||||
        <span v-if="!hasAvailablePlayers">
 | 
					        <span v-if="!hasAvailablePlayers && rosterStore.selectedRole">
 | 
				
			||||||
          No players are currently available for this role.
 | 
					          No players are currently available for this role.
 | 
				
			||||||
        </span>
 | 
					        </span>
 | 
				
			||||||
      </div>
 | 
					        <h3 v-if="hasAvailablePlayers">Alternates</h3>
 | 
				
			||||||
      <div class="column">
 | 
					        <PlayerCard v-for="player in rosterStore.alternateRoles"
 | 
				
			||||||
        <h3 v-if="hasAvailablePlayers">Available if needed</h3>
 | 
					 | 
				
			||||||
        <PlayerCard v-for="player in rosterStore.canBeAvailable"
 | 
					 | 
				
			||||||
                    :player="player"
 | 
					                    :player="player"
 | 
				
			||||||
                    :role-title="player.role" />
 | 
					                    :role-title="player.role" />
 | 
				
			||||||
 | 
					        <PlayerCard v-if="rosterStore.selectedRole"
 | 
				
			||||||
 | 
					                    is-ringer
 | 
				
			||||||
 | 
					                    :role-title="rosterStore.selectedRole" />
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </main>
 | 
					  </main>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style scoped>
 | 
					<style scoped>
 | 
				
			||||||
 | 
					.top {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: row;
 | 
				
			||||||
 | 
					  justify-content: space-between;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.top .button-group {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: row;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  gap: 8px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.columns {
 | 
					.columns {
 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  flex-direction: row;
 | 
					  flex-direction: row;
 | 
				
			||||||
| 
						 | 
					@ -57,8 +86,20 @@ const hasAvailablePlayers = computed(() => {
 | 
				
			||||||
  width: 100%;
 | 
					  width: 100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
h3 {
 | 
					.column h3 {
 | 
				
			||||||
  font-weight: 700;
 | 
					  font-weight: 700;
 | 
				
			||||||
  color: var(--subtext-0);
 | 
					  font-size: 14px;
 | 
				
			||||||
 | 
					  text-transform: uppercase;
 | 
				
			||||||
 | 
					  color: var(--overlay-0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.roster-title {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  gap: 0.5em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					em.aside.date {
 | 
				
			||||||
 | 
					  font-size: 14px;
 | 
				
			||||||
 | 
					  vertical-align: middle;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,79 @@
 | 
				
			||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import PlayerCard from "../components/PlayerCard.vue";
 | 
				
			||||||
 | 
					import RoleSlot from "../components/RoleSlot.vue";
 | 
				
			||||||
 | 
					import PlayerTeamRole from "../player.ts";
 | 
				
			||||||
 | 
					import { computed, reactive } from "vue";
 | 
				
			||||||
 | 
					import { useRosterStore } from "../stores/roster";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const rosterStore = useRosterStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const hasAvailablePlayers = computed(() => {
 | 
				
			||||||
 | 
					  return rosterStore.availablePlayerRoles.length > 0;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <main>
 | 
				
			||||||
 | 
					    <h1 class="roster-title">
 | 
				
			||||||
 | 
					      Roster for Snus Brotherhood
 | 
				
			||||||
 | 
					      <emph class="aside date">Aug. 13, 2036 @ 11:30 PM EST</emph>
 | 
				
			||||||
 | 
					    </h1>
 | 
				
			||||||
 | 
					    <div class="columns">
 | 
				
			||||||
 | 
					      <div class="column">
 | 
				
			||||||
 | 
					        <PlayerCard v-for="role in rosterStore.neededRoles"
 | 
				
			||||||
 | 
					                    :player="rosterStore.selectedPlayers[role]"
 | 
				
			||||||
 | 
					                    :role-title="role"
 | 
				
			||||||
 | 
					                    is-roster />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class="column">
 | 
				
			||||||
 | 
					        <h3 v-if="hasAvailablePlayers">Available</h3>
 | 
				
			||||||
 | 
					        <PlayerCard v-for="player in rosterStore.definitelyAvailableAll"
 | 
				
			||||||
 | 
					                    :player="player"
 | 
				
			||||||
 | 
					                    :role-title="player.role" />
 | 
				
			||||||
 | 
					        <span v-if="!hasAvailablePlayers">
 | 
				
			||||||
 | 
					          No players are currently available for this role.
 | 
				
			||||||
 | 
					        </span>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class="column">
 | 
				
			||||||
 | 
					        <h3 v-if="hasAvailablePlayers">Available if needed</h3>
 | 
				
			||||||
 | 
					        <PlayerCard v-for="player in rosterStore.canBeAvailableAll"
 | 
				
			||||||
 | 
					                    :player="player"
 | 
				
			||||||
 | 
					                    :role-title="player.role" />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </main>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style scoped>
 | 
				
			||||||
 | 
					.columns {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: row;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.column {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-grow: 1;
 | 
				
			||||||
 | 
					  margin-left: 4em;
 | 
				
			||||||
 | 
					  margin-right: 4em;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  row-gap: 8px;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.column h3 {
 | 
				
			||||||
 | 
					  font-weight: 700;
 | 
				
			||||||
 | 
					  font-size: 14px;
 | 
				
			||||||
 | 
					  text-transform: uppercase;
 | 
				
			||||||
 | 
					  color: var(--overlay-0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.roster-title {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  gap: 0.5em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					emph.aside.date {
 | 
				
			||||||
 | 
					  font-size: 14px;
 | 
				
			||||||
 | 
					  vertical-align: middle;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
		Loading…
	
		Reference in New Issue