mirror of
https://github.com/romancm/gamebrary
synced 2024-11-28 14:10:26 +00:00
refactor add game
This commit is contained in:
parent
fa3034f68a
commit
bfde8534bc
4 changed files with 158 additions and 275 deletions
|
@ -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();
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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';
|
||||
},
|
||||
},
|
||||
|
||||
|
|
Loading…
Reference in a new issue