mirror of
https://github.com/romancm/gamebrary
synced 2025-01-11 10:48:44 +00:00
226 lines
4.5 KiB
Vue
226 lines
4.5 KiB
Vue
<template lang="html">
|
|
<div class="add-game-modal">
|
|
<b-button
|
|
block
|
|
variant="light"
|
|
v-b-modal="`game-modal-${listId}`"
|
|
:title="$t('list.addGames', { listName })"
|
|
>
|
|
<b-icon-plus />
|
|
</b-button>
|
|
|
|
<b-modal
|
|
:id="`game-modal-${listId}`"
|
|
:title="$t('list.addGames', { listName })"
|
|
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>
|
|
|
|
<small
|
|
v-if="gamesInList.length > 0"
|
|
class="games-in-list"
|
|
:title="gamesInListNames"
|
|
>
|
|
<strong>{{ gamesInListMessage }}</strong>
|
|
{{ $t('gameSearch.alreadyInList') }}
|
|
</small>
|
|
|
|
<div
|
|
v-if="filteredResults.length > 0"
|
|
ref="searchResults"
|
|
class="search-results"
|
|
>
|
|
<legacy-game-card-search
|
|
v-for="{ id } in filteredResults"
|
|
:key="id"
|
|
:game-id="id"
|
|
:list-id="listId"
|
|
search-result
|
|
@added="added"
|
|
/>
|
|
</div>
|
|
|
|
<span
|
|
v-if="noResults"
|
|
class="no-results"
|
|
>
|
|
{{ $t('gameSearch.noResultsFound') }}
|
|
</span>
|
|
|
|
<template v-slot:modal-footer>
|
|
<igdb-logo />
|
|
</template>
|
|
</b-modal>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import LegacyGameCardSearch from '@/components/LegacyBoard/LegacyGameCardSearch';
|
|
import IgdbLogo from '@/components/IgdbLogo';
|
|
import { mapState } from 'vuex';
|
|
|
|
export default {
|
|
components: {
|
|
LegacyGameCardSearch,
|
|
IgdbLogo,
|
|
},
|
|
|
|
props: {
|
|
listId: {
|
|
type: [Number, String, Boolean],
|
|
required: true,
|
|
default: 0,
|
|
},
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
searchText: '',
|
|
loading: false,
|
|
};
|
|
},
|
|
|
|
computed: {
|
|
...mapState(['results', 'gameLists', 'platform']),
|
|
|
|
noResults() {
|
|
return !this.loading
|
|
&& this.filteredResults.length === 0
|
|
&& this.searchText.trim().length > 0;
|
|
},
|
|
|
|
list() {
|
|
return this.gameLists[this.platform.code];
|
|
},
|
|
|
|
listName() {
|
|
return this.list[this.listId].name;
|
|
},
|
|
|
|
filteredResults() {
|
|
return this.results.length
|
|
? this.results.filter(({ id }) => !this.list[this.listId].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))
|
|
: [];
|
|
},
|
|
|
|
gamesInListMessage() {
|
|
const gameCount = this.gamesInList.length;
|
|
const plural = gameCount === 1 ? '' : 's';
|
|
|
|
return `${gameCount} game${plural}`;
|
|
},
|
|
},
|
|
|
|
watch: {
|
|
searchText(value) {
|
|
if (value) {
|
|
this.loading = true;
|
|
this.search();
|
|
}
|
|
},
|
|
},
|
|
|
|
methods: {
|
|
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 }) => {
|
|
this.loading = false;
|
|
this.error = data;
|
|
});
|
|
|
|
this.error = null;
|
|
this.loading = false;
|
|
|
|
if (this.$refs.searchResults) {
|
|
this.$refs.searchResults.scrollTop = 0;
|
|
}
|
|
},
|
|
},
|
|
};
|
|
</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);
|
|
overflow-y: auto;
|
|
border-radius: var(--border-radius);
|
|
display: grid;
|
|
grid-gap: .5rem;
|
|
|
|
@media(max-width: 780px) {
|
|
max-height: calc(100vh - 200px);
|
|
}
|
|
}
|
|
</style>
|