Undangan/proyek-frontend/app/pages/p/[code].vue
2025-10-09 11:41:30 +07:00

71 lines
2.3 KiB
Vue

<template>
<div class="min-h-screen flex items-center justify-center bg-gray-100">
<div v-if="pending" class="text-center">
<div class="animate-spin rounded-full h-12 w-12 border-t-4 border-blue-500 mx-auto"></div>
<p class="mt-4 text-gray-600">Loading invitation...</p>
</div>
<div v-else-if="error" class="max-w-md w-full bg-white rounded-lg shadow-lg p-8 text-center">
<p class="text-red-600">{{ error }}</p>
</div>
<div v-else>
<component v-if="dynamicComponent" :is="dynamicComponent" :data="data" />
<div v-else class="max-w-md w-full bg-white rounded-lg shadow-lg p-8">
<h1 class="text-2xl font-bold text-gray-800 mb-4">Invitation Data</h1>
<div v-for="(value, key) in data" :key="key" class="mb-4">
<h2 class="text-lg font-semibold text-gray-700 capitalize">{{ key.replace('_', ' ') }}</h2>
<p v-if="typeof value !== 'object'" class="text-gray-600">{{ value }}</p>
<pre v-else class="text-gray-600 bg-gray-50 p-2 rounded">{{ JSON.stringify(value, null, 2) }}</pre>
</div>
</div>
</div>
</div>
</template>
<script setup>
const route = useRoute()
const config = useRuntimeConfig()
const backendUrl = config.public.apiBaseUrl
const error = ref(null)
const { data, pending } = await useAsyncData('invitation', async () => {
try {
const response = await $fetch(`${backendUrl}/api/pelanggans/code/${route.params.code}`)
if (!response.data || !response.data.template || !response.data.template.slug) {
throw new Error('Invalid API response structure')
}
return response.data
} catch (err) {
error.value = err.message || 'Failed to load invitation data'
return null
}
})
const componentMap = {
minimalis: defineAsyncComponent(() => import('~/components/undangan/undangan-minimalis.vue')),
/// impory
}
const dynamicComponent = computed(() => {
return data.value?.template?.slug ? componentMap[data.value.template.slug] || null : null
})
useHead({
title: data.value?.nama_pelanggan || 'Undangan Pernikahan',
meta: [
{ name: 'description', content: `Undangan pernikahan untuk ${data.value?.nama_pengantin || 'tamu undangan'}` },
],
})
</script>
<style scoped>
pre {
text-align: left;
white-space: pre-wrap;
word-wrap: break-word;
}
</style>