personal-site/components/PostCard.vue

189 lines
7.8 KiB
Vue
Raw Permalink Normal View History

2025-01-04 02:47:38 -08:00
<script setup lang="ts">
2024-12-21 19:11:09 -08:00
import { ref, watch } from 'vue';
import fm from 'front-matter';
2025-01-01 14:17:16 -08:00
import { auto } from '@popperjs/core';
2024-12-21 19:11:09 -08:00
const props = defineProps({
url: String,
2025-01-04 02:47:38 -08:00
tagFilter: Array<String>,
2025-01-01 14:17:16 -08:00
// Allow sm, md, and lg
size: {
type: String,
default: 'full',
validator: (value) => ['xs', 'sm', 'md', 'full'].includes(value)
}
2024-12-21 19:11:09 -08:00
});
2025-01-04 02:47:38 -08:00
const url: Ref<string> = ref("")
url.value = props.url as string
2024-12-21 19:11:09 -08:00
const loading = ref(false)
2025-01-04 02:47:38 -08:00
const error: Ref<string | null> = ref(null)
const markdown: Ref<any> = ref(null)
2024-12-21 19:11:09 -08:00
2025-01-04 02:47:38 -08:00
const background: Ref<string> = ref('');
const title: Ref<string> = ref("Untitled");
const description: Ref<string | null> = ref(null);
const date: Ref<string | null> = ref(null);
const tags: Ref<string | null> = ref(null);
2024-12-21 19:11:09 -08:00
2025-01-04 02:47:38 -08:00
watch(url, (newVal) => {
fetchData(newVal)
}, { immediate: true })
2025-01-01 14:17:16 -08:00
2025-01-04 02:47:38 -08:00
watch(markdown, (newVal) => {
if (newVal) {
title.value = newVal.title ? newVal.title : ""
description.value = newVal.description ? newVal.description : ""
date.value = newVal.date ? new Date(newVal.date).toLocaleDateString() : ""
tags.value = newVal.tags ? newVal.tags : []
background.value = newVal.background ? newVal.background : ""
2024-12-21 19:11:09 -08:00
2025-01-04 02:47:38 -08:00
console.log("Title: " + title.value)
console.log("Description: " + description.value)
console.log("Date: " + date.value)
console.log("Tags: " + tags.value)
console.log("Background: " + background.value)
}
})
async function fetchData(url: string) {
2024-12-21 19:11:09 -08:00
loading.value = true
2025-01-04 02:47:38 -08:00
// remove all .md extensions
const temp_url = url.replace(/\.md$/, '')
console.log("Fetching article: " + temp_url)
2024-12-21 19:11:09 -08:00
try {
2025-01-04 02:47:38 -08:00
const {data} = await useAsyncData(temp_url, () => queryContent(temp_url).findOne())
2025-01-01 14:17:16 -08:00
2025-01-04 02:47:38 -08:00
markdown.value = data.value;
} catch (err: any) {
2024-12-21 19:11:09 -08:00
error.value = err.toString()
loading.value = false
} finally {
loading.value = false
}
}
2025-01-04 02:47:38 -08:00
onMounted(() => {
fetchData(url.value)
})
2024-12-21 19:11:09 -08:00
</script>
<template>
2025-01-04 11:45:02 -08:00
<NuxtLink :href="'/article' + url">
2025-01-01 14:17:16 -08:00
<!-- Large -->
<div v-if = "size === 'full'">
<div class="m-4 min-h-30 min-width-90 text-white transition hover:bg-purple-600 bg-opacity-50 hover:bg-opacity-70">
<Card>
<div v-if="loading" class="text-center animate-pulse">
</div>
<div v-else-if="error" class="text-center">
<h2>Error: {{ error }}</h2>
<button @click="fetchData">Retry</button>
</div>
<div v-else>
<div class="grid">
<div class="justify-center">
<h1>{{ title }}</h1>
<small>{{ date }}</small>
</div>
<div class="flex justify-center">
<div v-for="tag in tags" :key="tag" class="m-1 text-center">
2025-01-04 02:47:38 -08:00
<div v-if="props.tagFilter?.includes(tag)">
2025-01-01 14:17:16 -08:00
<span class="text-xs bg-slate-700 border-white border-2 text-white p-1 rounded-md">{{ tag }}</span>
</div>
<div v-else>
<span class="text-xs bg-black border-purple-400 border-2 text-white p-1 rounded-md">{{ tag }}</span>
</div>
</div>
</div>
</div>
<p>{{ description }}</p>
</div>
</Card>
</div>
2024-12-21 19:11:09 -08:00
</div>
2025-01-01 14:17:16 -08:00
<!-- Medium -->
<div v-else-if = "size === 'md'">
<div class="m-4 min-h-30 min-width-50 text-white transition hover:bg-purple-600 bg-opacity-50 hover:bg-opacity-70">
<Card>
<div v-if="loading" class="text-center animate-pulse">
</div>
<div v-else-if="error" class="text-center">
<h2>Error: {{ error }}</h2>
<button @click="fetchData">Retry</button>
</div>
<div v-else>
<div class="grid">
<div class="justify-center">
<h2>{{ title }}</h2>
<small>{{ date }}</small>
</div>
<div class="flex justify-center">
<div v-for="tag in tags" :key="tag" class="m-1 text-center">
2025-01-04 02:47:38 -08:00
<div v-if="props.tagFilter?.includes(tag)">
2025-01-01 14:17:16 -08:00
<span class="text-xs bg-slate-700 border-white border-2 text-white p-1 rounded-md">{{ tag }}</span>
</div>
<div v-else>
<div class="flex justify-center">
<div v-for="tag in tags" :key="tag" class="m-1 text-center">
2025-01-04 02:47:38 -08:00
<div v-if="props.tagFilter?.includes(tag)">
2025-01-01 14:17:16 -08:00
<span class="text-xs bg-slate-700 border-white border-2 text-white p-1 rounded-md">{{ tag }}</span>
</div>
<div v-else>
<span class="text-xs bg-black border-purple-400 border-2 text-white p-1 rounded-md">{{ tag }}</span>
</div>
</div>
</div>
<span class="text-xs bg-black border-purple-400 border-2 text-white p-1 rounded-md">{{ tag }}</span>
</div>
</div>
</div>
</div>
</div>
</Card>
</div>
2024-12-21 19:11:09 -08:00
</div>
2025-01-01 14:17:16 -08:00
<!-- Small -->
<div v-else-if = "size === 'sm'">
<div class="m-4 min-h-30 min-width-30 text-white transition hover:bg-purple-600 bg-opacity-50 hover:bg-opacity-70">
<Card>
<div v-if="loading" class="text-center animate-pulse">
</div>
<div v-else-if="error" class="text-center">
<h2>Error: {{ error }}</h2>
<button @click="fetchData">Retry</button>
</div>
<div v-else>
<div class="grid">
<div class="justify-center">
<h3>{{ title }}</h3>
<small>{{ date }}</small>
</div>
2025-01-01 00:26:10 -08:00
</div>
2025-01-01 14:17:16 -08:00
</div>
</Card>
</div>
</div>
<!-- Extra Small -->
<div v-else-if = "size === 'xs'">
<div class="m-4 min-h-30 min-width-20 text-white transition hover:bg-purple-600 bg-opacity-50 hover:bg-opacity-70">
<Card>
<div v-if="loading" class="text-center animate-pulse">
</div>
<div v-else-if="error" class="text-center">
<h3>Error: {{ error }}</h3>
<button @click="fetchData">Retry</button>
</div>
<div v-else>
<div class="grid">
<div class="justify-center">
<h5>{{ title }}</h5>
</div>
2025-01-01 00:26:10 -08:00
</div>
2024-12-21 19:11:09 -08:00
</div>
2025-01-01 14:17:16 -08:00
</Card>
2024-12-21 19:11:09 -08:00
</div>
</div>
2024-12-22 12:22:47 -08:00
</NuxtLink>
2024-12-21 19:11:09 -08:00
</template>