230 lines
4.7 KiB
Vue
230 lines
4.7 KiB
Vue
<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>
|