refactor add game

This commit is contained in:
Gamebrary 2020-08-20 23:12:51 -07:00
parent fa3034f68a
commit bfde8534bc
4 changed files with 158 additions and 275 deletions

View file

@ -1,29 +1,31 @@
import moment from 'moment';
// import moment from 'moment';
import { mapState, mapGetters } from 'vuex';
export default {
props: {
gameId: Number,
listId: Number,
},
data() {
return {
showEditOptions: false,
};
list: {
type: Object,
default: () => {},
},
gameId: [String, Number],
},
computed: {
...mapState(['settings', 'games', 'gameLists', 'platform', 'user', 'tags', 'activeList', 'notes', 'progresses']),
// Remove unused stuff
...mapState(['settings', 'games', 'gameLists', 'platform', 'user', 'tags', 'activeList', 'notes', 'progresses', 'board']),
// TODO: remove getter
...mapGetters(['gameTags']),
showGameTags() {
return this.list.showGameTags && this.gameTags;
const { settings } = this.list;
return settings && settings.showGameTags && this.gameTags;
},
gameRating() {
return this.list.showGameRatings && this.game.rating
const { settings } = this.list;
return settings && settings.showGameRatings && this.game.rating
? Math.round((this.game.rating / 20) * 2) / 2
: false;
},
@ -36,38 +38,10 @@ export default {
: null;
},
releaseDate() {
const releaseDate = this.game
&& this.list.showReleaseDates
&& this.game.release_dates
&& this.game.release_dates.find(({ platform }) => this.platform.id === platform);
const formattedDate = releaseDate && releaseDate.date
? moment.unix(releaseDate.date)
: null;
return moment(formattedDate).isAfter()
? formattedDate.toNow(true)
: null;
},
gameCardClass() {
return [
'game-card',
this.list.view,
];
},
activePlatform() {
return this.gameLists[this.platform.code];
},
gameNotes() {
return this.list.showGameNotes && this.notes[this.gameId];
},
const { settings } = this.list;
list() {
return this.activePlatform[this.listId] || {};
return settings && settings.showGameNotes && this.notes[this.gameId];
},
game() {
@ -91,39 +65,12 @@ export default {
methods: {
openDetails() {
const { gameId, listId } = this;
const { gameId, list } = this;
this.$store.commit('SET_GAME_MODAL_DATA', { gameId, listId });
this.$store.commit('SET_GAME_MODAL_DATA', { gameId, list });
this.$bvModal.show('game-modal');
},
addGame() {
const data = {
listId: this.listId,
gameId: this.gameId,
};
this.$emit('added');
this.$store.commit('ADD_GAME_LEGACY', data);
this.$ga.event({
eventCategory: 'game',
eventAction: 'add',
eventLabel: 'addGame',
eventValue: data,
});
this.$store.dispatch('SAVE_LIST_LEGACY', this.gameLists)
.then(() => {
// TODO: customize, show cover url
this.$bvToast.toast(`Added ${this.game.name} to list ${this.list.name}`, { title: 'Game added', variant: 'success' });
})
.catch(() => {
this.$bvToast.toast('Authentication error', { title: 'Error', variant: 'danger' });
this.$router.push({ name: 'sessionExpired' });
});
},
removeTag(tagName) {
this.$store.commit('REMOVE_GAME_TAG', { tagName, gameId: this.gameId });
this.saveTags();

View file

@ -1,5 +1,5 @@
<template lang="html">
<b-card no-body class="game-card mb-2">
<b-card no-body class="game-card mb-1">
<b-row no-gutters v-if="game && game.name">
<b-col md="3">
<b-card-img
@ -42,9 +42,19 @@ import GameCardUtils from '@/components/GameCards/GameCard';
export default {
mixins: [GameCardUtils],
methods: {
async addGame() {
const { list, gameId, board } = this;
const listIndex = board.lists.findIndex(({ name }) => name === list.name);
this.$store.commit('ADD_GAME_TO_LIST', { listIndex, gameId });
await this.$store.dispatch('SAVE_BOARD');
// TODO: CUSTOMIZE TO SHOW GAME COVER
this.$bvToast.toast(`${this.game.name} added`, { title: list.name, variant: 'success' });
},
},
};
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
@import "GameCard";
</style>

View file

@ -3,66 +3,59 @@
<b-button
block
variant="light"
v-b-modal="`game-modal-${listId}`"
:title="$t('list.addGames', { listName })"
v-b-modal="`game-modal-${list.name}`"
:title="$t('list.addGames', { listName: list.name })"
>
<b-icon-plus />
</b-button>
<b-modal
:id="`game-modal-${listId}`"
:title="$t('list.addGames', { listName })"
:id="`game-modal-${list.name}`"
:title="$t('list.addGames', { listName: list.name })"
footer-class="p-2 justify-content-center"
@show="clear"
>
<form
@submit.prevent="search"
class="search-form"
>
<b-form-input
ref="searchInput"
v-model="searchText"
debounce="500"
:placeholder="$t('gameSearch.inputPlaceholder')"
type="text"
/>
<b-button @click="search">
<b-spinner v-if="loading" small label="Loading..." />
<b-icon-search v-else />
</b-button>
</form>
<b-form @submit.prevent="search" class="mb-2">
<b-input-group>
<b-form-input
v-model="searchText"
autofocus
debounce="500"
:placeholder="$t('gameSearch.inputPlaceholder')"
/>
<small
v-if="gamesInList.length > 0"
class="games-in-list"
:title="gamesInListNames"
>
<strong>{{ gamesInListMessage }}</strong>
{{ $t('gameSearch.alreadyInList') }}
</small>
<b-input-group-append>
<b-button variant="primary" @click="search">
<b-spinner v-if="loading" small label="Loading..." />
<b-icon-search v-else />
</b-button>
</b-input-group-append>
</b-input-group>
<div
<b-form-text v-if="gamesInList.length">
<strong>{{ gamesInList.length }}</strong>
{{ $t('gameSearch.alreadyInList') }}
</b-form-text>
</b-form>
<b-card
v-if="filteredResults.length > 0"
ref="searchResults"
class="search-results"
body-class="p-1 pb-0 search-results"
bg-variant="light"
>
<game-card-search
v-for="{ id } in filteredResults"
:key="id"
:game-id="id"
:list-id="listId"
search-result
@added="added"
:list="list"
/>
</div>
</b-card>
<span
v-if="noResults"
class="no-results"
>
<b-alert :show="noResults" variant="warning" class="mt-2 mb-0">
{{ $t('gameSearch.noResultsFound') }}
</span>
</b-alert>
<template v-slot:modal-footer>
<igdb-logo />
@ -83,10 +76,9 @@ export default {
},
props: {
listId: {
type: [Number, String, Boolean],
list: {
type: Object,
required: true,
default: 0,
},
},
@ -98,7 +90,7 @@ export default {
},
computed: {
...mapState(['results', 'gameLists', 'platform']),
...mapState(['results']),
noResults() {
return !this.loading
@ -106,36 +98,17 @@ export default {
&& this.searchText.trim().length > 0;
},
list() {
return this.gameLists[this.platform.code];
},
listName() {
return this.list[this.listId].name;
},
filteredResults() {
return this.results
? this.results.filter(({ id }) => !this.list[this.listId].games.includes(id))
? this.results.filter(({ id }) => !this.list.games.includes(id))
: [];
},
gamesInListNames() {
return this.gamesInList.map(({ name }) => name).join(', ');
},
gamesInList() {
return this.results
? this.results.filter(({ id }) => this.list[this.listId].games.includes(id))
? this.results.filter(({ id }) => this.list.games.includes(id))
: [];
},
gamesInListMessage() {
const gameCount = this.gamesInList.length;
const plural = gameCount === 1 ? '' : 's';
return `${gameCount} game${plural}`;
},
},
watch: {
@ -151,29 +124,12 @@ export default {
clear() {
this.searchText = '';
this.$store.commit('CLEAR_SEARCH_RESULTS');
this.focusInput();
},
focusInput() {
setTimeout(() => {
this.$refs.searchInput.focus();
}, 100);
},
added() {
this.$emit('added');
this.$bus.$emit('GAMES_ADDED');
if (this.filteredResults.length === 1) {
this.clear();
}
},
async search() {
await this.$store.dispatch('SEARCH_LEGACY', this.searchText)
.catch(({ data }) => {
await this.$store.dispatch('SEARCH_GAMES', this.searchText)
.catch(() => {
this.loading = false;
this.error = data;
});
this.error = null;
@ -188,36 +144,10 @@ export default {
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
.search-form {
display: flex;
align-items: center;
margin-bottom: 1rem;
input {
margin-bottom: 0;
}
button {
margin-left: 1rem;
}
}
.games-in-list {
margin-bottom: 1rem;
display: flex;
align-items: center;
strong {
margin-right: .2rem;
}
}
.search-results {
max-height: calc(100vh - 300px);
max-height: calc(100vh - 400px);
overflow-y: auto;
border-radius: var(--border-radius);
display: grid;
grid-gap: .5rem;
@media(max-width: 780px) {
max-height: calc(100vh - 200px);

View file

@ -9,35 +9,34 @@
<b-icon-sort-up />
</b-badge>
<b-badge v-if="list[listIndex].showGameCount">
{{ gameList.length }}
<b-badge v-if="showGameCount">
{{ list.games.length }}
</b-badge>
{{ list[listIndex].name }}
{{ list.name }}
</h6>
<b-button-group>
<add-game-modal :list-id="listIndex" />
<list-settings :list-index="listIndex" />
<add-game-modal :list="list" />
<!-- <list-settings :list-index="listIndex" /> -->
</b-button-group>
</b-card-header>
<draggable
class="games"
:list="gameList"
:id="listIndex"
:list="list.games"
:id="list.id"
:move="validateMove"
v-bind="gameDraggableOptions"
@end="dragEnd"
@start="dragStart"
>
<component
v-for="game in sortedGames"
v-for="game in list.games"
:is="gameCardComponent"
:key="game"
:id="game"
:list="list"
:game-id="game"
:list-id="listIndex"
/>
<b-button
@ -45,7 +44,7 @@
block
v-if="isEmpty"
class="mb-2"
v-b-modal="`game-modal-${listIndex}`"
v-b-modal="`game-modal-${list.name}`"
>
Click here or drag games here
</b-button>
@ -62,7 +61,7 @@ import GameCardGrid from '@/components/GameCards/GameCardGrid';
import GameCardCompact from '@/components/GameCards/GameCardCompact';
import GameCardText from '@/components/GameCards/GameCardText';
import AddGameModal from '@/components/Lists/AddGameModal';
import orderby from 'lodash.orderby';
// import orderby from 'lodash.orderby';
import { mapState } from 'vuex';
export default {
@ -77,18 +76,11 @@ export default {
},
props: {
name: {
type: String,
default: '',
},
gameList: {
type: Array,
default: () => [],
},
listIndex: {
type: Number,
default: null,
list: {
type: Object,
default: () => {},
},
required: true,
},
data() {
@ -114,72 +106,77 @@ export default {
},
computed: {
...mapState(['user', 'gameLists', 'platform', 'settings', 'games', 'dragging', 'progresses']),
...mapState(['games', 'dragging', 'progresses']),
autoSortEnabled() {
const list = this.list[this.listIndex];
const { settings } = this.list;
return list && list.sortOrder && list.sortOrder !== 'sortByCustom';
},
sortedGames() {
const sortOrder = this.list[this.listIndex].sortOrder || 'sortByCustom';
const { gameList } = this;
// TODO: use lodash to clean things up a bit here
switch (sortOrder) {
case 'sortByCustom':
return gameList;
case 'sortByProgress':
return orderby(gameList, [(game) => {
const progress = this.games[game]
&& this.progresses[this.platform.code][this.games[game].id]
? Number(this.progresses[this.platform.code][this.games[game].id])
: 0;
return progress;
}], ['desc']);
case 'sortByRating':
return orderby(gameList, [(game) => {
const rating = this.games[game] && this.games[game].rating
? this.games[game].rating
: 0;
return rating;
}], ['desc']);
case 'sortByName':
return orderby(gameList, [(game) => {
const name = this.games[game] && this.games[game].name
? this.games[game].name.toUpperCase()
: '';
return name;
}]);
case 'sortByReleaseDate':
return orderby(gameList, [(game) => {
const releaseDate = this.games[game] && this.games[game].release_dates
? this.games[game].release_dates
.find(({ platform }) => this.platform.id === platform)
: '';
return releaseDate && releaseDate.date;
}]);
default:
return gameList;
if (!settings) {
return false;
}
return ['sortByName', 'sortByRating', 'sortByReleaseDate', 'sortByProgress'].includes(settings.sortOrder);
},
list() {
return this.gameLists[this.platform.code];
},
// sortedGames() {
// const { settings } = this.list;
//
// const sortOrder = settings.sortOrder || 'sortByCustom';
//
// return gameList;
//
// // TODO: use lodash to clean things up a bit here
//
// switch (sortOrder) {
// case 'sortByCustom':
// return gameList;
// case 'sortByProgress':
// return orderby(this.list, [(game) => {
// const progress = this.games[game]
// && this.progresses[this.platform.code][this.games[game].id]
// ? Number(this.progresses[this.platform.code][this.games[game].id])
// : 0;
//
// return progress;
// }], ['desc']);
// case 'sortByRating':
// return orderby(this.list, [(game) => {
// const rating = this.games[game] && this.games[game].rating
// ? this.games[game].rating
// : 0;
//
// return rating;
// }], ['desc']);
// case 'sortByName':
// return orderby(this.list, [(game) => {
// const name = this.games[game] && this.games[game].name
// ? this.games[game].name.toUpperCase()
// : '';
//
// return name;
// }]);
// case 'sortByReleaseDate':
// return orderby(this.list, [(game) => {
// const releaseDate = this.games[game] && this.games[game].release_dates
// ? this.games[game].release_dates
// .find(({ platform }) => this.platform.id === platform)
// : '';
//
// return releaseDate && releaseDate.date;
// }]);
// default:
// return gameList;
// }
// },
isEmpty() {
return this.gameList.length === 0;
return this.list.games.length === 0;
},
view() {
return this.list[this.listIndex].view;
const { settings } = this.list;
return settings && settings.view;
},
unique() {
@ -187,25 +184,24 @@ export default {
},
showGameCount() {
return this.settings[this.platform.code] && this.settings[this.platform.code].showGameCount;
const { settings } = this.list;
return settings && settings.showGameCount;
},
gameCardComponent() {
return this.view && Object.keys(this.gameCardComponents).includes(this.view)
const availableViews = Object.keys(this.gameCardComponents);
return this.view && availableViews.includes(this.view)
? this.gameCardComponents[this.view]
: 'GameCardDefault';
},
viewClass() {
return this.list[this.listIndex].view || 'single';
},
showGameRatings() {
return this.list[this.listIndex].showGameRatings || false;
},
hideReleaseDates() {
return this.list[this.listIndex].hideReleaseDates || false;
return 'single';
// const { settings } = this.list;
//
// return this.list && .view || 'single';
},
},