diff --git a/composables/api/useContentAPI.ts b/composables/api/useContentAPI.ts new file mode 100644 index 0000000..478a1cb --- /dev/null +++ b/composables/api/useContentAPI.ts @@ -0,0 +1,46 @@ +import { BEST_ARTICLES_LIMIT, MOST_VIEWED_ARTICLES_LIMIT } from '~/configs/properties'; +import type { ArticleContent, ArticleListItem } from '~/types/responses'; + +const ARTICLE_LIST_ONLY: Array = ['_path', 'title', 'description', 'image', 'keywords']; +const ARTICLE_SIBLINGS_ONLY: Array = ['_path', 'title']; +const PAGINATION_LIMIT = 10; + +interface PaginationOptions { + skip?: number; + limit?: number; +} + +export default function useContentAPI() { + const fetchArticle = (path: string) => queryContent(path).findOne(); + + const fetchArticleSiblings = (path: string, topic?: string) => + queryContent() + .only(ARTICLE_SIBLINGS_ONLY) + .where({ _path: { $contains: `/articles/${topic}` } }) + .findSurround(path); + + const fetchArticlesListByTopic = (topic: string) => + queryContent(`articles/${topic}`).only(ARTICLE_LIST_ONLY).find(); + + const fetchMostViewedArticlesList = () => + queryContent('articles').only(ARTICLE_LIST_ONLY).limit(MOST_VIEWED_ARTICLES_LIMIT).find(); // TODO: update + + const fetchBestArticlesList = () => + queryContent('articles').only(ARTICLE_LIST_ONLY).limit(BEST_ARTICLES_LIMIT).find(); // TODO: update + + const fetchPaginalArticlesList = (options = {} as PaginationOptions) => + queryContent('articles') + .only(ARTICLE_LIST_ONLY) + .skip(options.skip ?? 0) + .limit(options.limit || PAGINATION_LIMIT) + .find(); + + return { + fetchArticle, + fetchArticleSiblings, + fetchArticlesListByTopic, + fetchMostViewedArticlesList, + fetchBestArticlesList, + fetchPaginalArticlesList, + }; +} diff --git a/configs/properties.ts b/configs/properties.ts index be5f1b0..6214487 100644 --- a/configs/properties.ts +++ b/configs/properties.ts @@ -41,3 +41,5 @@ export const ARTICLE_TOPICS = [ export const ARTICLE_KEYWORDS = ['api', 'architecture', 'design', 'fundamentals', 'perfomance', 'refactoring'] as const; export const MAX_ARTICLE_RATE = 5; export const ARTICLE_RATE_MAX_AGE = 30 * 24 * 60 * 60; +export const MOST_VIEWED_ARTICLES_LIMIT = 5; +export const BEST_ARTICLES_LIMIT = 5; diff --git a/pages/articles/[topic]/[slug].vue b/pages/articles/[topic]/[slug].vue index 21bf961..bd86cde 100644 --- a/pages/articles/[topic]/[slug].vue +++ b/pages/articles/[topic]/[slug].vue @@ -153,6 +153,7 @@ const pageTransition = useState('article-page-transition' const route = useRoute(); const { openSuccessfulSnackbar, openErrorSnackbar } = useSnackbar(); const { fetchArticleStats, updateArticleRate, updateArticleViews } = usePublicAPI(); +const { fetchArticle, fetchArticleSiblings } = useContentAPI(); const topic = route.params.topic as string; const title = route.params.slug as string; @@ -161,9 +162,7 @@ const rateCookie = useCookie(`article-rate-${topic}-${title}`, { maxAge: ARTICLE const rateModelValue = ref(0); -const { data: article, error } = await useAsyncData(route.path, () => - queryContent(route.path).sort({ id: 1, $numeric: true }).findOne(), -); +const { data: article, error } = await useAsyncData(route.path, () => fetchArticle(route.path), { deep: false }); if (!article.value || error.value) { throw createError({ statusCode: 404, data: { to: '/articles' }, fatal: true }); } @@ -175,15 +174,7 @@ const { data: stats, pending: statsPending } = await useLazyAsyncData( { deep: false }, ); -const { data: siblings } = await useLazyAsyncData( - () => - queryContent() - .only(['_path', 'title']) - .sort({ id: 1, $numeric: true }) - .where({ _path: { $contains: `/articles/${topic}` } }) - .findSurround(route.path), - { deep: false }, -); +const { data: siblings } = await useLazyAsyncData(() => fetchArticleSiblings(route.path, topic), { deep: false }); const prevSibling = computed(() => siblings.value?.[0] as ArticleContent | undefined); diff --git a/pages/articles/[topic]/index.vue b/pages/articles/[topic]/index.vue index fc779b8..2e87493 100644 --- a/pages/articles/[topic]/index.vue +++ b/pages/articles/[topic]/index.vue @@ -28,11 +28,9 @@