frontend/src/views/CollectionView/CollectionMerchCard.vue

139 lines
2.8 KiB
Vue
Raw Normal View History

2025-09-18 21:05:19 +03:00
<script setup>
2025-09-16 21:26:36 +03:00
import BoxIcon from '@/components/icons/BoxIcon.vue'
2025-10-18 14:10:21 +03:00
import { useMerchImagesApi } from '@/api/merchImages.js'
2025-10-29 20:58:47 +03:00
import { computed, onMounted, ref } from 'vue'
import LabelDotTemplate from '@/components/LabelDotTemplate.vue'
import { useLabelsStore } from '@/stores/labelsStore.js'
2025-10-18 14:10:21 +03:00
const { getImageUrl } = useMerchImagesApi()
2025-09-18 21:05:19 +03:00
2025-10-18 14:10:21 +03:00
const props = defineProps({
2025-09-18 21:05:19 +03:00
merch: {
type: Object,
required: true,
2025-10-29 20:58:47 +03:00
},
labels: {
type: Array,
default: () => [],
},
})
const store = useLabelsStore()
const resolvedLabelDots = computed(() => {
const labelMap = new Map()
for (const label of store.labels) {
labelMap.set(label.label_uuid, label)
2025-09-18 21:05:19 +03:00
}
2025-10-29 20:58:47 +03:00
return props.labels
.map(uuid => labelMap.get(uuid))
.filter(Boolean)
2025-09-18 21:05:19 +03:00
})
2025-10-18 14:10:21 +03:00
const fileList = ref([])
onMounted(async () => {
try {
2025-10-26 21:33:06 +03:00
const imgUrl = getImageUrl(props.merch.merch_uuid, 'thumbnail')
await new Promise((resolve, reject) => {
const img = new Image()
img.src = imgUrl
img.onload = () => resolve(imgUrl)
img.onerror = () => reject(new Error('Image not found'))
})
2025-10-18 14:10:21 +03:00
fileList.value = [
{
2025-10-26 21:33:06 +03:00
name: 'thumbnail.jpg',
2025-10-18 14:10:21 +03:00
url: imgUrl,
status: 'finished',
},
]
} catch (error) {
fileList.value = []
2025-10-26 21:33:06 +03:00
if (!error.message.includes('404')) {
console.error('Error getting thumbnail: ', error)
2025-10-18 14:10:21 +03:00
}
}
})
2025-09-16 21:26:36 +03:00
</script>
<template>
2025-09-25 20:04:48 +03:00
<n-card class="responsive-card">
<template #header>
<h3 class="card-title">{{ merch.name }}</h3>
2025-10-29 20:58:47 +03:00
<div v-if="resolvedLabelDots.length > 0" class="label-dots">
<LabelDotTemplate
v-for="label in resolvedLabelDots"
:key="label.label_uuid"
:color="label.color"
:bg_color="label.bg_color"
/>
</div>
2025-09-25 20:04:48 +03:00
</template>
2025-09-16 21:26:36 +03:00
<template #cover>
<div class="cover-wrapper">
2025-10-18 14:10:21 +03:00
<img
v-if="fileList.length > 0 && fileList[0].url"
:src="fileList[0].url"
alt="Thumbnail"
class="thumbnail"
/>
<BoxIcon v-else />
2025-09-16 21:26:36 +03:00
</div>
</template>
</n-card>
</template>
<style scoped>
.responsive-card {
2025-09-25 20:04:48 +03:00
width: 180px;
height: 240px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.card-title {
margin: 0;
font-size: 14px;
font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
white-space: normal;
2025-09-16 21:26:36 +03:00
}
.cover-wrapper {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
padding: 12px 0;
overflow: hidden;
}
2025-10-18 14:10:21 +03:00
.thumbnail {
width: 100%;
height: auto;
max-width: 80%;
object-fit: contain;
}
2025-09-16 21:26:36 +03:00
.cover-wrapper :deep(svg) {
width: 100%;
height: auto;
max-width: 80%;
}
2025-10-29 20:58:47 +03:00
.label-dots {
display: flex;
gap: 6px;
flex-wrap: wrap;
justify-content: right;
}
2025-09-16 21:26:36 +03:00
</style>