Files
chore/web/vue-app/src/components/ChildDetailCard.vue
2025-11-20 14:06:59 -05:00

124 lines
2.5 KiB
Vue

<script setup lang="ts">
import { defineProps, toRefs, ref, onMounted, onBeforeUnmount } from 'vue'
import { getCachedImageUrl, revokeAllImageUrls } from '../common/imageCache'
interface Child {
id: string | number
name: string
age: number
points?: number
image_id: string | null
}
const props = defineProps<{
child: Child | null
}>()
const { child } = toRefs(props)
const imageUrl = ref<string | null>(null)
const imageCacheName = 'images-v1'
const fetchImage = async (imageId: string) => {
try {
const url = await getCachedImageUrl(imageId, imageCacheName)
imageUrl.value = url
} catch (err) {
console.error('Error fetching child image:', err)
}
}
onMounted(() => {
if (child.value && child.value.image_id) {
fetchImage(child.value.image_id)
}
})
// Revoke created object URLs when component unmounts to avoid memory leaks
onBeforeUnmount(() => {
revokeAllImageUrls()
})
</script>
<template>
<div v-if="child" class="detail-card">
<h1>{{ child.name }}</h1>
<img v-if="imageUrl" :src="imageUrl" alt="Child Image" class="child-image" />
<div class="info">
<div class="info-item">
<span class="label">Age:</span>
<span class="value">{{ child.age }}</span>
</div>
<div class="info-item">
<span class="label">Points:</span>
<span class="value">{{ child.points ?? '—' }}</span>
</div>
</div>
</div>
</template>
<style scoped>
.detail-card {
background: white;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.18);
padding: 1.2rem 1rem;
max-width: 420px;
width: 100%;
box-sizing: border-box;
}
.detail-card h1 {
font-size: 1.3rem;
color: #333;
margin-bottom: 1rem;
text-align: center;
}
.child-image {
width: 64px;
height: 64px;
object-fit: cover;
border-radius: 50%;
display: block;
margin: 0 auto 0.7rem auto;
}
.info {
display: flex;
flex-direction: column;
gap: 0.6rem;
}
.info-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5rem 0.7rem;
background: #f5f5f5;
border-radius: 7px;
font-size: 0.98rem;
}
/* Even more compact on small screens */
@media (max-width: 480px) {
.detail-card {
padding: 0.7rem 0.4rem;
max-width: 98vw;
}
.detail-card h1 {
font-size: 1.05rem;
margin-bottom: 0.7rem;
}
.child-image {
width: 48px;
height: 48px;
margin-bottom: 0.5rem;
}
.info-item {
padding: 0.38rem 0.5rem;
font-size: 0.93rem;
}
}
</style>