Files
drop/components/GameCarousel.vue
DecDuck 8363de2eed Store overhaul (#142)
* feat: small library tweaks + company page

* feat: new store view

* fix: ci merge error

* feat: add genres to store page

* feat: sorting

* feat: lock game/version imports while their tasks are running

* feat: feature games

* feat: tag based filtering

* fix: make tags alphabetical

* refactor: move a bunch of i18n to common

* feat: add localizations for everything

* fix: title description on panel

* fix: feature carousel text

* fix: i18n footer strings

* feat: add tag page

* fix: develop merge

* feat: offline games support (don't error out if provider throws)

* feat: tag management

* feat: show library next to game import + small fixes

* feat: most of the company and tag managers

* feat: company text field editing

* fix: small fixes + tsgo experiemental

* feat: upload icon and banner

* feat: store infinite scrolling and bulk import mode

* fix: lint

* fix: add drop-base to prettier ignore
2025-07-30 13:40:49 +10:00

77 lines
1.9 KiB
Vue

<template>
<div ref="currentComponent">
<ClientOnly fallback-tag="span">
<VueCarousel :items-to-show="singlePage" :items-to-scroll="singlePage">
<VueSlide
v-for="(game, gameIdx) in games"
:key="gameIdx"
class="justify-start"
>
<GamePanel
:game="game"
:href="game ? `/store/${game.id}` : undefined"
:show-title-description="showGamePanelTextDecoration"
/>
</VueSlide>
<template #addons>
<VueNavigation />
</template>
</VueCarousel>
<template #fallback>
<div
class="flex flex-nowrap flex-row overflow-hidden whitespace-nowrap"
>
<SkeletonCard
v-for="index in 10"
:key="index"
:loading="true"
class="mr-3 flex-none"
/>
</div>
</template>
</ClientOnly>
</div>
</template>
<script setup lang="ts">
import type { GameModel } from "~/prisma/client/models";
import type { SerializeObject } from "nitropack";
const props = defineProps<{
items: Array<SerializeObject<GameModel>>;
min?: number;
width?: number;
}>();
const { showGamePanelTextDecoration } = await $dropFetch(`/api/v1/settings`);
const currentComponent = ref<HTMLDivElement>();
const min = computed(() => Math.max(props.min ?? 8, props.items.length));
const games: Ref<Array<SerializeObject<GameModel> | undefined>> = computed(() =>
Array(min.value)
.fill(0)
.map((_, i) => props.items[i]),
);
const singlePage = ref(2);
const sizeOfCard = 192 + 10;
const handleResize = () => {
singlePage.value =
(props.width ??
currentComponent.value?.parentElement?.clientWidth ??
window.innerWidth) / sizeOfCard;
};
onMounted(() => {
handleResize();
window.addEventListener("resize", handleResize);
});
onBeforeUnmount(() => {
window.removeEventListener("resize", handleResize);
});
</script>