rebuild search route with custom pages for tracks, album, and artists

This commit is contained in:
geoffrey45
2022-10-01 01:30:14 +03:00
committed by Mungai Njoroge
parent 264406aef4
commit 8e258eaf24
20 changed files with 240 additions and 60 deletions
+24 -5
View File
@@ -1,11 +1,30 @@
<template>
<div class="search-albums-view"></div>
<div class="search-albums-view grid-page" v-auto-animate>
<AlbumCard
v-for="album in search.albums.value"
:key="album.hash"
:album="album"
/>
</div>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import AlbumCard from "@/components/shared/AlbumCard.vue";
import useSearchStore from "@/stores/search";
const search = useSearchStore();
</script>
<style lang="scss">
.search-albums-view {
height: 100%;
}
// .search-albums-view.grid-page {
// max-height: 100%;
// display: grid;
// grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
// gap: 1.75rem 0;
// padding-bottom: 4rem;
// padding-right: $medium;
// overflow: auto;
// }
</style>
+13 -5
View File
@@ -1,11 +1,19 @@
<template>
<div class="search-artists-view"></div>
<div v-auto-animate class="search-artists-view grid-page">
<ArtistCard
v-for="artist in search.artists.value"
:key="artist.image"
:artist="artist"
/>
</div>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import ArtistCard from "@/components/shared/ArtistCard.vue";
import useSearchStore from "@/stores/search";
const search = useSearchStore();
</script>
<style lang="scss">
.search-artists-view {
height: 100%;
}
</style>
+137 -10
View File
@@ -1,20 +1,48 @@
<template>
<div class="search-view">
<div class="tabs">
<button v-for="page in pages">{{ page }}</button>
<button
v-for="page in pages"
:class="{ 'btn-active': page === $route.params.page }"
@click="
() => {
$router.push({ name: Routes.search, params: { page: page } });
search.switchTab(page);
}
"
>
{{ page }}
</button>
</div>
<div class="noscroll">
<component :is="getComponent()" />
<div ref="page" class="page noscroll" v-auto-animate>
<component :is="component" />
</div>
<button
class="load-more"
:class="{ 'btn-disabled': !canLoadMore }"
@click="loadMore"
>
Load more
</button>
</div>
</template>
<script setup lang="ts">
import { useRoute } from "vue-router";
import { computed, onMounted, ref } from "vue";
import TracksPage from "./tracks.vue";
import AlbumPage from "./albums.vue";
import ArtistPage from "./artists.vue";
import { Routes } from "@/composables/enums";
import useSearchStore from "@/stores/search";
import { focusElemByClass } from "@/utils";
// width of album and artist cards
const defaultItemCount = 6;
const gridItemWidth = 160;
const page = ref<HTMLElement>();
const search = useSearchStore();
enum pages {
tracks = "tracks",
@@ -23,10 +51,9 @@ enum pages {
}
const route = useRoute();
const page = route.params.page as string;
function getComponent() {
switch (page) {
const component = computed(() => {
switch (route.params.page) {
case pages.tracks:
return TracksPage;
case pages.albums:
@@ -38,22 +65,101 @@ function getComponent() {
default:
return TracksPage;
}
});
function loadTracks() {
search.loadTracks();
focusElemByClass("page-bottom-padding", 100);
}
function getGridRowItemCount() {
if (page.value?.offsetWidth === undefined) return defaultItemCount;
const page_width = page.value?.offsetWidth - 16;
return Math.floor(page_width / gridItemWidth);
}
function scrollToGridPageBottom() {
const elem = document.getElementsByClassName("grid-page")[0] as HTMLElement;
setTimeout(() => {
elem.scrollTo(0, elem.scrollHeight);
}, 250);
// const elemWidth = elem.offsetWidth;
// console.log(Math.floor(elemWidth / 160));
// elem.scroll({
// top: elem.scrollHeight,
// behavior: "smooth",
// });
}
function loadAlbums() {
scrollToGridPageBottom();
setTimeout(() => {
// search.loadAlbums();
const itemCount = getGridRowItemCount();
search.loadAlbums(itemCount);
scrollToGridPageBottom();
}, 250);
}
function loadArtists() {
// const itemCount = getGridRowItemCount();
search.loadArtists();
scrollToGridPageBottom();
}
function loadMore() {
switch (route.params.page) {
case pages.tracks:
loadTracks();
break;
case pages.albums:
loadAlbums();
break;
case pages.artists:
loadArtists();
break;
default:
break;
}
}
const canLoadMore = computed(() => {
switch (route.params.page) {
case pages.tracks:
return search.tracks.more;
case pages.albums:
return search.albums.more;
case pages.artists:
return search.artists.more;
default:
false;
}
});
onMounted(() => {
search.switchTab(route.params.page as string);
});
</script>
<style lang="scss">
.search-view {
height: calc(100% - 1rem);
width: calc(100% - $small);
display: grid;
gap: 1rem;
grid-template-rows: max-content 1fr;
margin-right: -0.75rem;
.tabs {
width: fit-content;
display: flex;
gap: 1rem;
// margin: 0 auto;
margin-bottom: 1rem;
& > * {
background-color: $gray4;
@@ -62,5 +168,26 @@ function getComponent() {
text-transform: capitalize;
}
}
.page.noscroll {
overflow-x: visible;
}
.grid-page {
max-height: 100%;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
gap: 1.75rem 0;
padding-bottom: 4rem;
padding-right: 1rem;
overflow: auto;
}
button.load-more {
width: 10rem;
margin: 0 auto;
}
}
</style>
+7 -4
View File
@@ -3,7 +3,6 @@
<div class="noscroll">
<Layout :no_header="true" :tracks="search.tracks.value" />
</div>
<button @click.prevent="search.loadTracks">Load More</button>
</div>
</template>
@@ -18,9 +17,13 @@ const search = useSearchStore();
.search-tracks-view {
height: 100%;
display: grid;
grid-template-rows: 1fr max-content;
gap: 1rem;
.noscroll {
height: 100%;
}
.header-list-layout {
width: 100%;
}
button {
width: fit-content;