Files
Website/resources/js/views/Article.vue
2023-09-13 19:55:47 +10:00

164 lines
4.9 KiB
Vue

<template>
<SMLoading class="pt-24 pb-48" v-if="pageLoading" />
<SMPageStatus
v-else-if="!pageLoading && pageStatus != 200"
:status="pageStatus" />
<template v-else>
<div
class="max-w-4xl mx-auto h-96 text-center mb-8 relative rounded-4 overflow-hidden">
<div
class="blur bg-cover bg-center absolute top-0 left-0 w-full h-full -z-1 opacity-50"
:style="{
backgroundImage: `url('${backgroundImageUrl}')`,
}"></div>
<img :src="backgroundImageUrl" class="h-full" />
</div>
<div class="max-w-4xl mx-auto flex flex-col px-4">
<h1 class="pb-2 text-gray-6">
{{ article.title }}
</h1>
<div
class="flex flex-1 flex-justify-between flex-items-center pb-4">
<div>
<div class="font-bold text-gray-4">
{{ formattedDate(article.publish_at) }}
</div>
</div>
<router-link
v-if="userHasPermission('admin/articles') && article.id"
role="button"
:to="{
name: 'dashboard-article-edit',
params: { id: article.id },
}"
class="font-medium px-6 py-1.5 rounded-md hover:shadow-md transition text-sm border-1 bg-white border-sky-6 text-sky-600 text-center"
>Edit Article</router-link
>
</div>
<SMHTML :html="article.content" />
<SMImageGallery
v-if="article.gallery.length > 0"
:model-value="article.gallery" />
<SMAttachments
v-if="article.attachments.length > 0"
:model-value="article.attachments || []" />
</div>
</template>
</template>
<script setup lang="ts">
import { ref, Ref } from "vue";
import { useRoute } from "vue-router";
import SMAttachments from "../components/SMAttachments.vue";
import { api } from "../helpers/api";
import { Article, ArticleCollection, User } from "../helpers/api.types";
import { SMDate } from "../helpers/datetime";
import { useApplicationStore } from "../store/ApplicationStore";
import { mediaGetVariantUrl } from "../helpers/media";
import { userHasPermission } from "../helpers/utils";
import SMLoading from "../components/SMLoading.vue";
import SMPageStatus from "../components/SMPageStatus.vue";
import SMHTML from "../components/SMHTML.vue";
import SMImageGallery from "../components/SMImageGallery.vue";
const applicationStore = useApplicationStore();
/**
* The article data.
*/
let article: Ref<Article> = ref({
id: "",
created_at: "",
updated_at: "",
title: "",
slug: "",
user_id: "",
user: { display_name: "" },
content: "",
publish_at: "",
hero: {},
gallery: [],
attachments: [],
});
/**
* The current page error.
*/
let pageStatus = ref(200);
/**
* Is the page loading.
*/
let pageLoading = ref(false);
/**
* Article user.
*/
let articleUser: User | null = null;
/**
* Thumbnail image URL.
*/
let backgroundImageUrl = ref("");
/**
* Load the page data.
*/
const handleLoad = async () => {
let slug = useRoute().params.slug || "";
pageLoading.value = true;
if (slug.length > 0) {
let result = await api.get({
url: "/articles",
params: {
slug: `=${slug}`,
limit: 1,
},
callback: (result) => {
if (result.status < 300) {
const data = result.data as ArticleCollection;
if (data && data.articles && data.total && data.total > 0) {
article.value = data.articles[0];
article.value.publish_at = new SMDate(
article.value.publish_at,
{
format: "ymd",
utc: true,
},
).format("yyyy/MM/dd HH:mm:ss");
backgroundImageUrl.value = mediaGetVariantUrl(
article.value.hero,
"large",
);
applicationStore.setDynamicTitle(article.value.title);
} else {
pageStatus.value = 404;
}
} else {
pageStatus.value = result.status;
}
pageLoading.value = false;
},
});
} else {
pageStatus.value = 404;
}
};
/**
* Format Date
* @param dateStr Date string.
* @returns Formatted date.
*/
const formattedDate = (dateStr) => {
return new SMDate(dateStr, { format: "yMd" }).format("MMMM d, yyyy");
};
handleLoad();
</script>