Update roster builder

master
John Montagu, the 4th Earl of Sandvich 2024-10-24 15:13:35 -07:00
parent 684590e738
commit c08f2434e6
Signed by: sandvich
GPG Key ID: 9A39BE37E602B22D
7 changed files with 246 additions and 65 deletions

View File

@ -28,6 +28,8 @@ header {
}
nav {
display: flex;
gap: 8px;
width: 100%;
font-size: 12px;
text-align: center;
@ -35,21 +37,19 @@ nav {
}
nav a.router-link-exact-active {
color: var(--flamingo);
}
nav a.router-link-exact-active:hover {
background-color: transparent;
color: var(--crust);
background-color: var(--accent);
}
nav a {
padding: 0.5rem 1rem;
color: var(--subtext-0);
border-radius: 8px;
}
nav a:hover {
color: var(--crust);
background-color: var(--flamingo);
color: var(--accent);
background-color: var(--accent-transparent);
}
@media (min-width: 1024px) {

View File

@ -20,19 +20,25 @@
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
--text: #c6d0f5;
--subtext-1: #b8c0e0;
--subtext-0: #a5adcb;
--overlay-2: #939ab7;
--overlay-1: #8087a2;
--overlay-0: #6e738d;
--text: #4c4f69;
--subtext-1: #5c5f77;
--subtext-0: #6c6f85;
--overlay-2: #7c7f93;
--overlay-1: #8c8fa1;
--overlay-0: #9ca0b0;
--surface-0: #ccd0da;
--base: #eff1f5;
--mantle: #e6e9ef;
--crust: #dce0e8;
--surface-0: #363a4f;
--base: #24273a;
--mantle: #1e2030;
--crust: #181926;
--flamingo: #f0c6c6;
--flamingo-transparent: #f0c6c655;
--green: #a6e3a1;
--lavender: #7287fd;
--accent: var(--lavender);
--accent-transparent: color-mix(in srgb, var(--accent), transparent 80%);
}
/* semantic color variables for this project */

View File

@ -11,20 +11,24 @@
a,
.green {
text-decoration: none;
color: var(--flamingo);
color: var(--accent);
transition: 0.4s;
padding: 3px;
}
@media (hover: hover) {
a:hover {
background-color: var(--flamingo-transparent);
background-color: var(--accent-transparent);
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
button {
color: var(--text);
border: none;
}
h1 {
font-weight: 800;
font-size: 300%;
}

View File

@ -1,6 +1,6 @@
<script setup lang="ts">
import type { PlayerTeamRole } from "../player";
import type { PropType } from "vue";
import { computed, type PropType } from "vue";
import { useRosterStore } from "../stores/roster";
const rosterStore = useRosterStore();
@ -11,19 +11,29 @@ const props = defineProps({
isRoster: Boolean,
});
const isSelected = computed(() => {
if (props.isRoster) {
return rosterStore.selectedRole == props.roleTitle;
}
return Object.values(rosterStore.selectedPlayers).includes(props.player);
});
function onClick() {
if (props.isRoster) {
rosterStore.selectedRole = props.roleTitle;
} else {
// we are selecting the player
rosterStore.selectPlayerForRole(props.player, props.roleTitle);
}
};
</script>
<template>
<div :class="{
<button :class="{
'player-card': true,
'no-player': !player,
'selected': rosterStore.selectedRole == roleTitle && isRoster
}" @click="onClick">
'selected': isSelected,
}" @click="onClick">
<div v-if="player">
<h1>{{ player.name }}</h1>
<span v-if="roleTitle != player.role">
@ -37,7 +47,7 @@ function onClick() {
<div v-else>
{{ roleTitle }}
</div>
</div>
</button>
</template>
<style scoped>
@ -49,12 +59,18 @@ function onClick() {
}
.player-card:hover {
background-color: var(--overlay-0);
background-color: var(--surface-0);
transition-duration: 200ms;
}
.player-card.no-player {
border: 2px solid var(--overlay-0);
border: 2px dashed var(--overlay-0);
}
.player-card.no-player.selected {
background-color: var(--accent-transparent);
border: 2px dashed var(--accent);
color: var(--accent);
}
.player-card.no-player:not(.selected) {
@ -67,12 +83,14 @@ function onClick() {
}
.player-card.selected {
background-color: var(--flamingo);
border-color: var(--flamingo);
color: var(--crust);
border-color: var(--accent);
border: 2px solid var(--accent);
background-color: var(--accent-transparent);
color: var(--accent);
}
h1 {
font-size: 24px;
font-weight: 700;
}
</style>

View File

@ -8,4 +8,5 @@ export interface PlayerTeamRole {
name: string;
role: string;
main: boolean;
availability: number;
}

View File

@ -1,13 +1,158 @@
import { type Player } from "@/player";
import { type Player, type PlayerTeamRole } from "@/player";
import { defineStore } from "pinia";
import { reactive, ref, type Reactive, type Ref } from "vue";
import { computed, reactive, ref, type Reactive, type Ref } from "vue";
export const useRosterStore = defineStore("roster", () => {
const neededRoles: Reactive<Array<String>> = reactive([
"Pocket Scout",
"Flank Scout",
"Pocket Soldier",
"Roamer",
"Demoman",
"Medic",
]);
const selectedPlayers: Reactive<{ [key: string]: PlayerTeamRole }> = reactive({});
const selectedRole: Ref<String | undefined> = ref("Pocket Scout");
const availablePlayers: Reactive<Array<Player>> = reactive([]);
const availablePlayers: Reactive<Array<PlayerTeamRole>> = reactive([
{
steamId: 2840,
name: "Wesker U",
role: "Flank Scout",
main: true,
availability: 1,
},
{
steamId: 2839,
name: "JustGetAHouse",
role: "Flank Scout",
main: false,
availability: 1,
},
{
steamId: 2839,
name: "JustGetAHouse",
role: "Pocket Scout",
main: true,
availability: 1,
},
{
steamId: 2841,
name: "VADIKUS007",
role: "Pocket Soldier",
main: true,
availability: 2,
},
{
steamId: 2841,
name: "VADIKUS007",
role: "Roamer",
main: false,
availability: 2,
},
{
steamId: 2282,
name: "Bergman777",
role: "Demoman",
main: true,
availability: 2,
},
{
steamId: 2842,
name: "BossOfThisGym",
role: "Roamer",
main: false,
availability: 2,
},
{
steamId: 2842,
name: "BossOfThisGym",
role: "Demoman",
main: false,
availability: 2,
},
{
steamId: 2842,
name: "BossOfThisGym",
role: "Pocket Scout",
main: false,
availability: 2,
},
//{
// steamId: 2843,
// name: "samme1g",
// role: "Medic",
// main: true,
// availability: 2,
//},
{
steamId: 2843,
name: "samme1g",
role: "Pocket Soldier",
main: false,
availability: 2,
},
{
steamId: 2843,
name: "samme1g",
role: "Roamer",
main: false,
availability: 2,
},
{
steamId: 2844,
name: "FarbrorBarbro",
role: "Roamer",
main: true,
availability: 1,
},
{
steamId: 2844,
name: "FarbrorBarbro",
role: "Pocket Soldier",
main: false,
availability: 1,
},
]);
const availablePlayerRoles = computed(() => {
return availablePlayers.filter((player) => player.role == selectedRole.value);
});
const definitelyAvailable = computed(() => {
return availablePlayerRoles.value.filter((player) => player.availability == 2);
});
const canBeAvailable = computed(() => {
return availablePlayerRoles.value.filter((player) => player.availability == 1);
});
function selectPlayerForRole(player: PlayerTeamRole, role: string) {
console.log("selecting.");
if (player) {
const existingRole = Object.keys(selectedPlayers).find((selectedRole) => {
return selectedPlayers[selectedRole]?.steamId == player.steamId &&
role != selectedRole;
});
if (existingRole) {
delete selectedPlayers[existingRole];
}
}
selectedPlayers[role] = player;
}
return {
neededRoles,
selectedPlayers,
selectedRole,
availablePlayers,
availablePlayerRoles,
selectPlayerForRole,
definitelyAvailable,
canBeAvailable,
}
});

View File

@ -2,42 +2,43 @@
import PlayerCard from "../components/PlayerCard.vue";
import RoleSlot from "../components/RoleSlot.vue";
import PlayerTeamRole from "../player.ts";
import { reactive } from "vue";
import { computed, reactive } from "vue";
import { useRosterStore } from "../stores/roster";
const rosterStore = useRosterStore();
const testPlayer: PlayerTeamRole = {
name: "JustGetAHouse",
role: "Pocket Scout",
main: false,
}
const testPlayer2: PlayerTeamRole = {
name: "Wesker U",
role: "Pocket Scout",
main: true,
}
const players = [testPlayer, testPlayer2];
const selectPlayers = reactive();
const hasAvailablePlayers = computed(() => {
return rosterStore.availablePlayerRoles.length > 0;
});
</script>
<template>
<div class="columns">
<div class="column">
{{ rosterStore.selectedRole }}
<PlayerCard :player="testPlayer" role-title="Pocket Scout" is-roster />
<PlayerCard role-title="Flank Scout" is-roster />
<PlayerCard role-title="Pocket Soldier" is-roster />
<PlayerCard role-title="Roamer" is-roster />
<PlayerCard role-title="Demoman" is-roster />
<PlayerCard role-title="Medic" is-roster />
<main>
<h1>Roster</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.definitelyAvailable"
: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.canBeAvailable"
:player="player"
:role-title="player.role" />
</div>
</div>
<div class="column">
</div>
</div>
</main>
</template>
<style scoped>
@ -53,5 +54,11 @@ const selectPlayers = reactive();
margin-right: 4em;
flex-direction: column;
row-gap: 8px;
width: 100%;
}
h3 {
font-weight: 700;
color: var(--subtext-0);
}
</style>