merge with forntend and add category to main category slug genrator
This commit is contained in:
@@ -18,7 +18,7 @@ const isMobile = useMediaQuery('(max-width: 1024px)');
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="columns-1 xs:columns-2 xl:columns-3 gap-6 sm:gap-8 w-full space-y-8">
|
||||
<div class="grid grid-cols-1 xs:grid-cols-2 xl:grid-cols-3 gap-6 sm:gap-8 w-full space-y-8">
|
||||
<BlogPost
|
||||
v-for="article in articles"
|
||||
:key="article.id"
|
||||
|
||||
@@ -29,85 +29,83 @@ const createdAt = usePersianTimeAgo(new Date(date.value));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<NuxtLink
|
||||
:to="`/article/${slug}`"
|
||||
:class="variant === 'lg' ? 'aspect-square rounded-150 overflow-hidden' : 'h-fit'"
|
||||
class="group w-full relative block"
|
||||
<NuxtLink
|
||||
:to="`/article/${slug}`"
|
||||
:class="variant === 'lg' ? 'aspect-square rounded-150 overflow-hidden' : 'h-fit'"
|
||||
class="group w-full relative block"
|
||||
>
|
||||
<Tag
|
||||
v-if="variant === 'lg'"
|
||||
class="bg-slate-950 absolute left-6 top-6 z-20"
|
||||
>
|
||||
<Tag
|
||||
v-if="variant === 'lg'"
|
||||
class="bg-slate-950 absolute left-6 top-6 z-20"
|
||||
>
|
||||
{{ category.name }}
|
||||
</Tag>
|
||||
|
||||
<div
|
||||
v-if="variant === 'sm'"
|
||||
class="aspect-square w-full rounded-150 overflow-hidden relative"
|
||||
>
|
||||
<Tag class="bg-slate-950 absolute z-20 left-4 sm:left-6 top-4 sm:top-6 max-sm:text-xs">
|
||||
{{ category.name }}
|
||||
</Tag>
|
||||
|
||||
<div
|
||||
v-if="variant === 'sm'"
|
||||
class="aspect-square w-full rounded-150 overflow-hidden relative"
|
||||
>
|
||||
<Tag class="bg-slate-950 absolute z-20 left-4 sm:left-6 top-4 sm:top-6 max-sm:text-xs">
|
||||
{{ category.name }}
|
||||
</Tag>
|
||||
|
||||
<NuxtImg
|
||||
:src="image"
|
||||
class="group-hover:scale-105 transition-transform duration-200 absolute size-full object-cover z-10"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
:class="variant === 'lg' ? 'absolute px-6' : 'invert mt-6'"
|
||||
class="bottom-6 lg:bottom-8 flex flex-col gap-4 z-20"
|
||||
>
|
||||
<div class="flex items-center gap-4 lg:gap-6">
|
||||
<div class="flex items-center gap-2">
|
||||
<Icon
|
||||
name="ci:comment"
|
||||
class="**:stroke-white size-3 md:size-3.5"
|
||||
/>
|
||||
<span class="typo-p-xs md:typo-p-sm text-white"> ۰ نظر </span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Icon
|
||||
name="ci:calendar"
|
||||
class="**:stroke-white size-3 md:size-3.5"
|
||||
/>
|
||||
<span class="typo-p-xs md:typo-p-sm text-white">
|
||||
{{ createdAt }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-4 flex-col">
|
||||
<span
|
||||
:class="variant === 'lg' ? 'line-clamp-2' : ''"
|
||||
class="text-base md:text-lg font-medium lg:typo-h-6 text-white"
|
||||
>
|
||||
{{ title }}
|
||||
</span>
|
||||
<p
|
||||
v-if="variant === 'sm'"
|
||||
class="text-white typo-p-xs max-sm:!leading-[175%] sm:typo-p-sm md:typo-p-md line-clamp-3"
|
||||
>
|
||||
تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو
|
||||
در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NuxtImg
|
||||
v-if="variant === 'lg'"
|
||||
:src="image"
|
||||
class="group-hover:scale-105 transition-transform duration-200 absolute size-full object-cover z-10"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="variant === 'lg'"
|
||||
class="w-full h-full bg-linear-to-t from-black to-transparent absolute inset-0 z-15"
|
||||
/>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<div
|
||||
:class="variant === 'lg' ? 'absolute px-6' : 'invert mt-6'"
|
||||
class="bottom-6 lg:bottom-8 flex flex-col gap-4 z-20"
|
||||
>
|
||||
<div class="flex items-center gap-4 lg:gap-6">
|
||||
<div class="flex items-center gap-2">
|
||||
<Icon
|
||||
name="ci:comment"
|
||||
class="**:stroke-white size-3 md:size-3.5"
|
||||
/>
|
||||
<span class="typo-p-xs md:typo-p-sm text-white"> ۰ نظر </span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Icon
|
||||
name="ci:calendar"
|
||||
class="**:stroke-white size-3 md:size-3.5"
|
||||
/>
|
||||
<span class="typo-p-xs md:typo-p-sm text-white">
|
||||
{{ createdAt }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-4 flex-col">
|
||||
<span
|
||||
:class="variant === 'lg' ? 'line-clamp-2' : ''"
|
||||
class="text-base md:text-lg font-medium lg:typo-h-6 text-white"
|
||||
>
|
||||
{{ title }}
|
||||
</span>
|
||||
<p
|
||||
v-if="variant === 'sm'"
|
||||
class="text-white typo-p-xs max-sm:!leading-[175%] sm:typo-p-sm md:typo-p-md line-clamp-3"
|
||||
>
|
||||
تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در
|
||||
زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NuxtImg
|
||||
v-if="variant === 'lg'"
|
||||
:src="image"
|
||||
class="group-hover:scale-105 transition-transform duration-200 absolute size-full object-cover z-10"
|
||||
alt=""
|
||||
/>
|
||||
|
||||
<div
|
||||
v-if="variant === 'lg'"
|
||||
class="w-full h-full bg-linear-to-t from-black to-transparent absolute inset-0 z-15"
|
||||
/>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
@@ -18,15 +18,13 @@ await suspense();
|
||||
<NuxtLink to="/articles">
|
||||
<Button
|
||||
variant="primary"
|
||||
class="rounded-full max-sm:typo-label-sm max-sm:py-2"
|
||||
class="rounded-full max-md:h-[38px] max-md:text-xs"
|
||||
end-icon="ci:arrow-left"
|
||||
>
|
||||
نمایش همه
|
||||
</Button>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<ArticlesList
|
||||
:articles="[...articles!.results,...articles!.results,...articles!.results,...articles!.results,...articles!.results,...articles!.results]"
|
||||
/>
|
||||
<ArticlesList :articles="articles!.results" />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -38,15 +38,18 @@ const submitComment = async () => {
|
||||
|
||||
const limitedComments = computed(() => {
|
||||
if (showMoreComments.value) {
|
||||
return comments.value!.results;
|
||||
return comments.value?.results;
|
||||
}
|
||||
|
||||
return comments.value!.results.slice(0, 3);
|
||||
return comments.value?.results.slice(0, 3);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="bg-slate-50">
|
||||
<section
|
||||
v-if="!!comments"
|
||||
class="bg-slate-50"
|
||||
>
|
||||
<div class="flex relative gap-8 my-42 container max-lg:flex-col">
|
||||
<div
|
||||
class="sticky top-0 flex flex-col gap-6 lg:min-w-[400px] h-fit bg-white p-8 rounded-xl border-[0.5px] border-slate-200"
|
||||
@@ -99,13 +102,13 @@ const limitedComments = computed(() => {
|
||||
/>
|
||||
|
||||
<div
|
||||
v-if="comments!.count > 0"
|
||||
v-if="comments.count > 0"
|
||||
class="flex items-center justify-center w-full"
|
||||
>
|
||||
<Pagination
|
||||
v-if="showMoreComments"
|
||||
:total="comments!.count"
|
||||
:items="comments!.results.map((item, i) => ({ type: 'page', value: i }))"
|
||||
:total="comments.count"
|
||||
:items="comments.results.map((item, i) => ({ type: 'page', value: i }))"
|
||||
/>
|
||||
<Button
|
||||
v-else
|
||||
|
||||
@@ -17,7 +17,7 @@ const useGetProduct = (id: string | number | undefined) => {
|
||||
// methods
|
||||
|
||||
const handleGetProduct = async (id: string | number | undefined) => {
|
||||
const { data } = await axios.get<GetProductResponse>(`${API_ENDPOINTS.product.get}/${id}`);
|
||||
const { data } = await axios.get<GetProductResponse>(`${API_ENDPOINTS.product.get}/${id}/`);
|
||||
return data;
|
||||
};
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ export default defineNuxtConfig({
|
||||
"@vite-pwa/nuxt",
|
||||
"@nuxt/image",
|
||||
"@nuxtjs/seo",
|
||||
"motion-v/nuxt",
|
||||
],
|
||||
|
||||
sitemap: {
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
"gsap": "^3.12.7",
|
||||
"highlight.js": "^11.11.1",
|
||||
"jalali-ts": "^8.0.0",
|
||||
"motion-v": "^1.1.1",
|
||||
"nuxt": "^3.15.4",
|
||||
"reka-ui": "^1.0.0-alpha.6",
|
||||
"sanitize-html": "^2.15.0",
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
import ChatButton from "~/components/product/ChatBox/ChatButton.vue";
|
||||
import useGetProduct from "~/composables/api/product/useGetProduct";
|
||||
import useGetComments from "~/composables/api/product/useGetComments";
|
||||
import ProductsSlider from "~/components/global/product-detail/ProductsSlider.vue";
|
||||
|
||||
// state
|
||||
@@ -11,10 +10,8 @@ import ProductsSlider from "~/components/global/product-detail/ProductsSlider.vu
|
||||
const route = useRoute();
|
||||
|
||||
const id = route.params.id as string | undefined;
|
||||
const page = ref(1);
|
||||
|
||||
const { suspense: suspenseProduct, data: product } = useGetProduct(id);
|
||||
const { suspense: suspenseComments } = useGetComments(id, page);
|
||||
|
||||
useSeoMeta({
|
||||
title: `محصول ${product.value?.name}`,
|
||||
@@ -45,9 +42,8 @@ provide("productVariant", {
|
||||
// ssr
|
||||
|
||||
const productResponse = await suspenseProduct();
|
||||
const commentsResponse = await suspenseComments();
|
||||
|
||||
if (productResponse.isError || commentsResponse.isError) {
|
||||
if (productResponse.isError ) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: `error : product ${id} prefetch error`,
|
||||
|
||||
Reference in New Issue
Block a user