153 lines
3.9 KiB
Vue
153 lines
3.9 KiB
Vue
<template>
|
|
<div>
|
|
<PageHeader
|
|
title="Update"
|
|
subtitle="Member update"
|
|
theme="stone"
|
|
size="medium"
|
|
/>
|
|
|
|
<section class="py-12 px-4">
|
|
<UContainer class="px-4">
|
|
<!-- Loading State -->
|
|
<div v-if="loading" class="flex justify-center items-center py-20">
|
|
<div class="text-center">
|
|
<div
|
|
class="w-8 h-8 border-4 border-stone-500 border-t-transparent rounded-full animate-spin mx-auto mb-4"
|
|
></div>
|
|
<p class="text-stone-400">Loading update...</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Update Content -->
|
|
<div v-else-if="update" class="max-w-3xl">
|
|
<UpdateCard
|
|
:update="update"
|
|
:show-preview="false"
|
|
@edit="handleEdit"
|
|
@delete="handleDelete"
|
|
/>
|
|
|
|
<!-- Comments Placeholder -->
|
|
<div
|
|
class="mt-8 p-8 border border-stone-700 rounded-lg bg-stone-800/30"
|
|
>
|
|
<h3 class="text-lg font-semibold text-stone-200 mb-4">Comments</h3>
|
|
<p class="text-stone-400 text-center py-8">Comments coming soon</p>
|
|
</div>
|
|
|
|
<!-- Back Button -->
|
|
<div class="mt-6">
|
|
<UButton
|
|
to="/updates"
|
|
variant="ghost"
|
|
color="neutral"
|
|
icon="i-lucide-arrow-left"
|
|
>
|
|
Back to Updates
|
|
</UButton>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Error State -->
|
|
<div v-else-if="error" class="text-center py-20">
|
|
<p class="text-stone-400 mb-4">{{ error }}</p>
|
|
<UButton to="/updates" variant="outline" color="neutral">
|
|
Back to Updates
|
|
</UButton>
|
|
</div>
|
|
</UContainer>
|
|
</section>
|
|
|
|
<!-- Delete Confirmation Modal -->
|
|
<UModal
|
|
v-model:open="showDeleteModal"
|
|
title="Delete Update?"
|
|
description="Are you sure you want to delete this update? This action cannot be undone."
|
|
>
|
|
<template #footer>
|
|
<div class="flex justify-end gap-3">
|
|
<UButton
|
|
variant="ghost"
|
|
color="neutral"
|
|
@click="showDeleteModal = false"
|
|
>
|
|
Cancel
|
|
</UButton>
|
|
<UButton color="red" :loading="deleting" @click="confirmDelete">
|
|
Delete
|
|
</UButton>
|
|
</div>
|
|
</template>
|
|
</UModal>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
const route = useRoute();
|
|
|
|
const update = ref(null);
|
|
const loading = ref(true);
|
|
const error = ref(null);
|
|
const showDeleteModal = ref(false);
|
|
const deleting = ref(false);
|
|
|
|
// Load update
|
|
const loadUpdate = async () => {
|
|
loading.value = true;
|
|
error.value = null;
|
|
|
|
try {
|
|
const data = await $fetch(`/api/updates/${route.params.id}`);
|
|
update.value = data;
|
|
console.log("✅ Update loaded successfully:", data);
|
|
} catch (err) {
|
|
console.error("❌ Failed to load update:", err);
|
|
console.error("Error details:", {
|
|
status: err.statusCode,
|
|
message: err.data?.statusMessage,
|
|
data: err.data,
|
|
});
|
|
error.value =
|
|
err.data?.statusMessage || err.statusMessage || "Update not found";
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
onMounted(() => {
|
|
loadUpdate();
|
|
});
|
|
|
|
const handleEdit = () => {
|
|
navigateTo(`/updates/${route.params.id}/edit`);
|
|
};
|
|
|
|
const handleDelete = () => {
|
|
showDeleteModal.value = true;
|
|
};
|
|
|
|
const confirmDelete = async () => {
|
|
deleting.value = true;
|
|
try {
|
|
await $fetch(`/api/updates/${route.params.id}`, {
|
|
method: "DELETE",
|
|
});
|
|
|
|
// Redirect to updates feed
|
|
await navigateTo("/updates");
|
|
} catch (err) {
|
|
console.error("Failed to delete update:", err);
|
|
alert("Failed to delete update. Please try again.");
|
|
deleting.value = false;
|
|
}
|
|
};
|
|
|
|
useHead({
|
|
title: computed(() =>
|
|
update.value
|
|
? `Update by ${update.value.author?.name} - Ghost Guild`
|
|
: "Update - Ghost Guild",
|
|
),
|
|
});
|
|
</script>
|