mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-04 20:43:04 +00:00
rebuild search route with custom pages for tracks, album, and artists
This commit is contained in:
committed by
Mungai Njoroge
parent
264406aef4
commit
8e258eaf24
@@ -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>
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user