mlpcardgame/src/components/DeckBuilder/DeckList.vue

230 lines
4.7 KiB
Vue
Raw Normal View History

<template>
<section class="decklist">
<section class="card-section" v-for="section in sections" :key="section">
<header>
<h1>{{ section }}</h1>
</header>
<article
class="ccgcard"
@click="() => _drop(card)"
v-for="(card, i) in getCards(section, true)"
:key="i"
>
<img :src="imageURL(card.data.ID)" class="cardbg" />
<div class="amt">{{ card.howmany }}</div>
<div class="fullname">
<div class="name">{{ card.data.Name }}</div>
<div class="subname">
{{ card.data.Subname ? card.data.Subname : "" }}
</div>
</div>
</article>
</section>
</section>
</template>
<style lang="scss" scoped>
@import "@/assets/scss/_variables.scss";
.decklist {
display: flex;
flex-direction: column;
}
.card-section {
header {
h1 {
padding: 5px 10px;
font-family: $fantasy;
font-size: 10pt;
}
}
}
.ccgcard {
display: flex;
align-content: space-between;
align-items: center;
border: 1px solid $grey;
border-radius: 10px;
padding: 5px 3px;
margin: 2px 0;
cursor: pointer;
position: relative;
overflow: hidden;
div {
z-index: 2;
}
}
.cardbg {
position: absolute;
margin-top: 30%;
right: -20px;
left: -20px;
max-width: none;
width: 120%;
filter: brightness(20%);
z-index: 1;
}
.fullname {
display: flex;
flex-direction: column;
}
.amt {
margin: 0 6pt 0 10pt;
font-weight: bold;
font-size: 13pt;
&:after {
content: " ×";
font-weight: 300;
}
}
.name {
font-family: $fantasy;
font-size: 10.5pt;
line-height: 1rem;
}
.subname {
color: $grey-light;
font-size: 10pt;
line-height: 1rem;
}
</style>
<script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator";
import {
cardFullName,
CardSlot,
Card,
cardImageURL,
multiElemStr,
typeNames
} from "@/mlpccg";
function sortCards(a: CardSlot, b: CardSlot): number {
// Sort by element
// (Cards are guaranteed to be the same type)
switch (a.data.Type) {
case "Friend":
{
// Sort by requirement
if (a.data.Requirement && b.data.Requirement) {
const reqA = multiElemStr(Object.keys(a.data.Requirement));
const reqB = multiElemStr(Object.keys(b.data.Requirement));
if (reqA > reqB) {
return 1;
}
if (reqB > reqA) {
return -1;
}
}
// Sort by cost
if (a.data.Cost && b.data.Cost) {
if (a.data.Cost > b.data.Cost) {
return 1;
}
if (a.data.Cost < b.data.Cost) {
return -1;
}
}
// Sort by element
const elemA = multiElemStr(a.data.Element);
const elemB = multiElemStr(b.data.Element);
if (elemA > elemB) {
return 1;
}
if (elemB > elemA) {
return -1;
}
}
break;
case "Problem":
if (a.data.ProblemRequirement && b.data.ProblemRequirement) {
const preqA = multiElemStr(Object.keys(a.data.ProblemRequirement));
const preqB = multiElemStr(Object.keys(b.data.ProblemRequirement));
if (preqA > preqB) {
return 1;
}
if (preqB > preqA) {
return -1;
}
}
break;
case "Event":
case "Resource":
if (a.data.Requirement && b.data.Requirement) {
const reqA = multiElemStr(Object.keys(a.data.Requirement));
const reqB = multiElemStr(Object.keys(b.data.Requirement));
if (reqA > reqB) {
return 1;
}
if (reqB > reqA) {
return -1;
}
}
break;
}
// Sort by power
if (a.data.Power && b.data.Power) {
if (a.data.Power > b.data.Power) {
return 1;
}
if (a.data.Power < b.data.Power) {
return -1;
}
}
// If all else fail, sort by name
const nameA = cardFullName(a.data);
const nameB = cardFullName(b.data);
if (nameA > nameB) {
return 1;
}
if (nameA < nameB) {
return -1;
}
return 0;
}
@Component({
components: {}
})
export default class DeckList extends Vue {
@Prop()
public cards!: CardSlot[];
private fullName(card: Card): string {
return cardFullName(card);
}
private _drop(slot: CardSlot) {
this.$emit("removed", slot);
}
private imageURL(id: string) {
return cardImageURL(id);
}
private getCards(section: string, sort: boolean): CardSlot[] {
let cards = this.cards.filter(c => c.data.Type == section);
if (!sort) {
return cards;
}
return cards.sort(sortCards);
}
private get sections(): string[] {
return typeNames.filter(s => this.getCards(s, false).length > 0);
}
}
</script>