This commit is contained in:
Mamalizz
2025-02-02 23:07:07 +03:30
59 changed files with 3028 additions and 398 deletions
+115
View File
@@ -0,0 +1,115 @@
<script lang="ts" setup>
// import
import { sanitize } from "isomorphic-dompurify";
import useGetArticle from "~/composables/api/blog/useGetArticle";
// state
const route = useRoute();
const id = route.params.id as string | undefined;
const { data: article, suspense } = useGetArticle(id);
// ssr
const response = await suspense();
if (response.isError) {
throw createError({
statusCode: 500,
statusMessage: `Error in categories page prefetch`
});
}
// computed
const sanitizedArticleContent = computed(() => {
return sanitize(article.value!.content);
});
const sanitizedArticleSummery = computed(() => {
return sanitize(article.value!.summery);
});
</script>
<template>
<div class="container">
<div class="w-full h-[80svh] rounded-3xl relative overflow-hidden">
<img class="absolute object-cover size-full" :alt="article!.title" :src="article!.cover_image" />
<div class="absolute bg-linear-to-t from-black/75 to-transparent size-full" />
<div class="absolute pl-10 right-10 bottom-10 flex flex-col gap-6">
<h1 class="typo-h-4 text-white pl-8">
{{ article!.title }}
</h1>
<div
class="typo-p-lg text-slate-200 mb-6 text-justify w-[70%]"
v-html="sanitizedArticleSummery"
/>
<div class="flex items-center justify-between">
<div class="flex items-center gap-4">
<div
class="w-fit pr-2 pl-5 h-[50px] rounded-full flex items-center justify-center gap-3 bg-white">
<div
class="relative flex items-center justify-center rounded-full overflow-hidden size-[35px]">
<img
class="size-full object-cover absolute"
:src="article!.author.profile_photo"
alt="article-author"
/>
</div>
<span class="typo-label-sm">
{{ article!.author.full_name }}
</span>
</div>
<div
class="w-fit pr-4 pl-5 h-[50px] rounded-full flex items-center justify-center gap-2 border-[1.5px] border-white text-white">
<span class="typo-label-sm mt-0.5">
دسته بندی موبایل
</span>
</div>
</div>
<div class="flex items-center gap-4">
<div
class="w-fit pr-4 pl-5 h-[50px] rounded-full flex items-center justify-center gap-2 border-[1.5px] border-white text-white">
<Icon name="ci:calendar" size="24px" class="**:stroke-white" />
<span class="typo-label-sm mt-0.5">
۲۴ مهر 1403
</span>
</div>
<div
class="w-fit pr-4 pl-5 h-[50px] rounded-full flex items-center justify-center gap-2 border-[1.5px] border-white text-white">
<Icon name="ci:eye-open" size="24px" class="**:stroke-white" />
<span class="typo-label-sm mt-0.5">
{{ article!.views }}
</span>
</div>
</div>
</div>
</div>
</div>
<div class="flex gap-4 mt-8">
<div
class="p-8 flex-1 text-zinc-800 flex flex-col gap-6 [&_p,ul]:text-zinc-500 [&_h1]:typo-h-4 [&_h2]:typo-h-5 [&_h3]:typo-h-6 [&_p]:typo-p-md [&_ul]:list-disc [&_ul]:typo-p-md [&_ul]:space-y-2"
v-html="sanitizedArticleContent"
/>
<aside class="mt-8 p-8 h-fit bg-slate-100 w-[400px] sticky top-4 rounded-3xl">
asdsa
</aside>
</div>
</div>
</template>
+15 -53
View File
@@ -3,6 +3,7 @@
// import
import useGetArticles from "~/composables/api/blog/useGetArticles";
import ArticlesList from "~/components/articles/ArticlesList.vue";
// state
@@ -14,17 +15,15 @@ const { data: articles, suspense } = useGetArticles(page, debouncedSearch);
// ssr
await useAsyncData(async () => {
const response = await suspense();
const response = await suspense();
if (response.isError) {
throw createError({
statusCode: 500,
statusMessage: `Error in categories page prefetch`
});
}
if (response.isError) {
throw createError({
statusCode: 500,
statusMessage: `Error in categories page prefetch`
});
}
});
</script>
<template>
@@ -50,50 +49,13 @@ await useAsyncData(async () => {
</template>
</Input>
</div>
<div class="flex gap-12">
<div class="flex-1 flex flex-col gap-12">
<BlogPost
image="/img/blog-1.jpeg"
description="aaasd"
title="asd"
:comments="2"
link="#"
date="2020-06-10"
tag="asdsa"
/>
<BlogPost
image="/img/blog-2.jpeg"
description="aaasd"
title="asd"
:comments="2"
link="#"
date="2020-06-10"
tag="asdsa"
/>
</div>
<div class="flex-[0.8] flex flex-col">
<BlogPost
image="/img/blog-3.jpeg"
description="aaasd"
title="asd"
:comments="2"
link="#"
date="2020-06-10"
tag="asdsa"
variant="sm"
/>
<BlogPost
image="/img/blog-4.jpeg"
description="aaasd"
title="asd"
:comments="2"
link="#"
date="2020-06-10"
tag="asdsa"
variant="sm"
/>
</div>
</div>
<!-- This is for masonry js package -->
<ClientOnly>
<ArticlesList :articles="articles!.results" />
</ClientOnly>
<div class="w-full flex-center pt-24 pb-10">
<Pagination :items="[]" :total="100" />
</div>
+8 -11
View File
@@ -31,17 +31,14 @@ const filteredCategories = computed(() => {
// ssr
await useAsyncData(async () => {
const response = await suspense();
const response = await suspense();
if (response.isError) {
throw createError({
statusCode: 500,
statusMessage: `Error in categories page prefetch`
});
}
});
if (response.isError) {
throw createError({
statusCode: 500,
statusMessage: `Error in categories page prefetch`
});
}
</script>
@@ -79,7 +76,7 @@ await useAsyncData(async () => {
>
<div class="w-full flex items-center justify-between gap-8">
<div class="flex items-center gap-2">
<!-- <img :src="mainCategory.icon" alt="" class="w-[30px] opacity-50" />-->
<!-- <img :src="mainCategory.icon" alt="" class="w-[30px] opacity-50" />-->
<span class="typo-h-5">
{{ mainCategory.name }}
</span>
+7 -9
View File
@@ -10,16 +10,14 @@ const { suspense } = useHomeData();
// ssr
await useAsyncData(async () => {
const response = await suspense();
const response = await suspense();
if (response.isError) {
throw createError({
statusCode: 500,
statusMessage: `Landing error : ${response.error.message}`,
})
}
});
if (response.isError) {
throw createError({
statusCode: 500,
statusMessage: `Landing error : ${response.error.message}`
});
}
</script>
+10 -12
View File
@@ -9,22 +9,20 @@ const route = useRoute();
const id = route.params.id as string | undefined;
const page = ref(1);
const { suspense : suspenseProduct } = useGetProduct(id);
const { suspense : suspenseComments} = useGetComments(id, page);
const { suspense: suspenseProduct } = useGetProduct(id);
const { suspense: suspenseComments } = useGetComments(id, page);
// ssr
await useAsyncData(async () => {
const productResponse = await suspenseProduct();
const commentsResponse = await suspenseComments();
const productResponse = await suspenseProduct();
const commentsResponse = await suspenseComments();
if (productResponse.isError || commentsResponse.isError) {
throw createError({
statusCode: 404,
statusMessage: `error : product ${id} prefetch error`
});
}
});
if (productResponse.isError || commentsResponse.isError) {
throw createError({
statusCode: 404,
statusMessage: `error : product ${id} prefetch error`
});
}
</script>
+2
View File
@@ -158,6 +158,7 @@ const resetForm = () => {
class="flex items-center gap-2 w-full"
>
<Input
data-testid="phone-input"
class="w-full"
v-model="loginInfo.phone"
placeholder="9380123456"
@@ -185,6 +186,7 @@ const resetForm = () => {
/>
<Button
data-testid="send-otp-code-button"
v-if="!showOtp"
class="rounded-full w-full mt-4"
type="submit"