detail blog
This commit is contained in:
+100
-53
@@ -1,16 +1,80 @@
|
|||||||
|
'use client'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import { Calendar, Eye, User } from 'iconsax-react'
|
import { Calendar, Eye, User, Share } from 'iconsax-react'
|
||||||
import LastPost from '../components/LastPost'
|
import LastPost from '../components/LastPost'
|
||||||
import { NextPage } from 'next'
|
import { NextPage } from 'next'
|
||||||
import Layout from '@/hoc/Layout'
|
import Layout from '@/hoc/Layout'
|
||||||
import { SHOP_CONFIG } from '@/config/const'
|
import { SHOP_CONFIG } from '@/config/const'
|
||||||
|
import { useGetBlogDetails, useGetLastBlogs } from '../hooks/useBlogData'
|
||||||
|
import { useParams } from 'next/navigation'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
const BlogDetail: NextPage = () => {
|
const BlogDetail: NextPage = () => {
|
||||||
|
|
||||||
|
const { id } = useParams()
|
||||||
|
const { data, isLoading } = useGetBlogDetails(id as string)
|
||||||
|
const { data: lastBlogsData } = useGetLastBlogs(3)
|
||||||
|
const [currentUrl, setCurrentUrl] = useState('')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
setCurrentUrl(window.location.href)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const shareOnTelegram = () => {
|
||||||
|
const blog = data?.results?.blog
|
||||||
|
if (blog && currentUrl) {
|
||||||
|
const text = `مشاهده مقاله: ${blog.title_fa}`
|
||||||
|
const url = `https://t.me/share/url?url=${encodeURIComponent(currentUrl)}&text=${encodeURIComponent(text)}`
|
||||||
|
window.open(url, '_blank')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const shareOnWhatsApp = () => {
|
||||||
|
const blog = data?.results?.blog
|
||||||
|
if (blog && currentUrl) {
|
||||||
|
const text = `${blog.title_fa}\n\n${currentUrl}`
|
||||||
|
const url = `https://wa.me/?text=${encodeURIComponent(text)}`
|
||||||
|
window.open(url, '_blank')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleNativeShare = async () => {
|
||||||
|
const blog = data?.results?.blog
|
||||||
|
if (blog && currentUrl && typeof navigator !== 'undefined' && 'share' in navigator) {
|
||||||
|
try {
|
||||||
|
const shareData = {
|
||||||
|
title: blog.title_fa,
|
||||||
|
text: `مشاهده مقاله: ${blog.title_fa}`,
|
||||||
|
url: currentUrl,
|
||||||
|
}
|
||||||
|
await (navigator as { share: (data: typeof shareData) => Promise<void> }).share(shareData)
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error sharing:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <div className="flex justify-center items-center min-h-screen">
|
||||||
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data?.results?.blog) {
|
||||||
|
return <div className="flex justify-center items-center min-h-screen">
|
||||||
|
<p className="text-gray-500">بلاگ یافت نشد</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
const blog = data.results.blog
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-7xl mx-auto px-4 py-8">
|
<div className="max-w-7xl mx-auto px-4 py-8">
|
||||||
{/* Breadcrumb */}
|
{/* Breadcrumb */}
|
||||||
<div className="text-sm text-gray-500 mb-6">
|
<div className="text-sm text-gray-500 mb-6">
|
||||||
فروشگاه {SHOP_CONFIG.name} / راهنما ها / تست اقلام و قطعات / گلکسی بوک
|
فروشگاه {SHOP_CONFIG.name} / {blog.category.title_fa} / {blog.title_fa}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-8">
|
<div className="flex gap-8">
|
||||||
@@ -19,25 +83,25 @@ const BlogDetail: NextPage = () => {
|
|||||||
{/* Blog Header */}
|
{/* Blog Header */}
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<div className="bg-orange-100 text-orange-600 px-3 py-1 rounded text-sm inline-block mb-4">
|
<div className="bg-orange-100 text-orange-600 px-3 py-1 rounded text-sm inline-block mb-4">
|
||||||
اخبار
|
{blog.category.title_fa}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-2xl font-bold text-gray-900 mb-4 leading-relaxed">
|
<h1 className="text-2xl font-bold text-gray-900 mb-4 leading-relaxed">
|
||||||
مشخصات گلکسی بوک 3 پرو و اولترا پیش از رونمایی فاش شد
|
{blog.title_fa}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div className="flex items-center gap-6 text-gray-500 text-sm">
|
<div className="flex items-center gap-6 text-gray-500 text-sm">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<User size={16} color="#9CA3AF" />
|
<User size={16} color="#9CA3AF" />
|
||||||
<span>نویسنده: حمید ضرغامی</span>
|
<span>نویسنده: {blog.author.fullName}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Calendar size={16} color="#9CA3AF" />
|
<Calendar size={16} color="#9CA3AF" />
|
||||||
<span>چهارشنبه 15 آذر 1401 ساعت 15:30</span>
|
<span>{new Date(blog.createdAt).toLocaleDateString('fa-IR')}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Eye size={16} color="#9CA3AF" />
|
<Eye size={16} color="#9CA3AF" />
|
||||||
<span>1,234 بازدید</span>
|
<span>{blog.view} بازدید</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -45,8 +109,8 @@ const BlogDetail: NextPage = () => {
|
|||||||
{/* Featured Image */}
|
{/* Featured Image */}
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<Image
|
<Image
|
||||||
src="https://images.unsplash.com/photo-1496181133206-80ce9b88a853?w=1200&h=600&fit=crop"
|
src={blog.imageUrl}
|
||||||
alt="Samsung Galaxy Book3 Ultra"
|
alt={blog.title_fa}
|
||||||
width={1200}
|
width={1200}
|
||||||
height={600}
|
height={600}
|
||||||
className="w-full h-[400px] object-cover rounded-lg"
|
className="w-full h-[400px] object-cover rounded-lg"
|
||||||
@@ -54,48 +118,20 @@ const BlogDetail: NextPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Blog Content */}
|
{/* Blog Content */}
|
||||||
<div className="prose prose-lg max-w-none text-gray-800 leading-8">
|
<div
|
||||||
<p className="text-lg leading-8 mb-6">
|
className="prose prose-lg max-w-none text-gray-800 leading-8"
|
||||||
گلکسی بوک 3 اولترا قویترین عضو این خانواده خواهد بود که با پردازنده نسل سیزدهم اینتل Core i9-13900H، حداکثر 32 گیگابایت رم LPDDR5 و 1 ترابایت حافظه داخلی NVMe PCIe Gen 4 از آن میرسد. این دستگاه همچنین میتواند به حداکثر گرافیک RTX 4070 اویدیا مجهز شود.
|
dangerouslySetInnerHTML={{ __html: blog.content }}
|
||||||
</p>
|
/>
|
||||||
|
|
||||||
<h2 className="text-xl font-bold mt-8 mb-4">گلکسی بوک 3 پرو</h2>
|
|
||||||
|
|
||||||
<p className="mb-6 leading-8">
|
|
||||||
گلکسی بوک 3 پرو در دو اندازه 14 و 16 اینچی عرضه میشود که هر دو از نوع اموled با روزنمایی 3K خواهند بود. این لپتاپ قرار است از پردازنده نسل سیزدهم اینتل Core i7-1360P و Core i5-1340P برخوردار شود؛ بههمراه حداکثر 1 ترابایت حافظه DDR5 رم و 16 گیگابایت استفاده کند 16 گیگابایت رم.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="bg-gray-50 p-6 rounded-lg mb-6">
|
|
||||||
<h3 className="font-bold text-lg mb-4">مشخصات فنی کلیدی:</h3>
|
|
||||||
<ul className="space-y-2">
|
|
||||||
<li>• پردازنده: Intel Core i9-13900H (نسل سیزدهم)</li>
|
|
||||||
<li>• رم: تا 32 گیگابایت LPDDR5</li>
|
|
||||||
<li>• حافظه: 1 ترابایت NVMe PCIe Gen 4</li>
|
|
||||||
<li>• کارت گرافیک: RTX 4070</li>
|
|
||||||
<li>• صفحه نمایش: OLED با کیفیت 3K</li>
|
|
||||||
<li>• سیستم عامل: Windows 11</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p className="mb-6 leading-8">
|
|
||||||
این لپتاپ برای کاربران حرفهای طراحی شده که نیاز به قدرت پردازشی بالا برای کارهای گرافیکی، ویرایش ویدئو و بازی دارند. طراحی زیبا و ساخت با کیفیت سامسونگ، آن را به گزینهای جذاب برای کسانی تبدیل میکند که به دنبال ترکیب عملکرد و زیبایی هستند.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 className="text-xl font-bold mt-8 mb-4">نتیجه گیری</h2>
|
|
||||||
|
|
||||||
<p className="mb-6 leading-8">
|
|
||||||
سامسونگ با ارائه گلکسی بوک 3 سری، قصد دارد جایگاه خود را در بازار لپتاپهای پریمیوم تقویت کند. این محصولات با ترکیب سختافزار قدرتمند و طراحی شیک، میتوانند رقیبی جدی برای سایر برندهای معتبر باشند.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Tags */}
|
{/* Tags */}
|
||||||
<div className="mt-8 pt-6 border-t border-gray-200">
|
<div className="mt-8 pt-6 border-t border-gray-200">
|
||||||
<div className="flex items-center gap-2 flex-wrap">
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
<span className="text-gray-600 font-medium">برچسبها:</span>
|
<span className="text-gray-600 font-medium">برچسبها:</span>
|
||||||
<span className="bg-primary/10 text-primary px-3 py-1 rounded-full text-sm">سامسونگ</span>
|
{blog.tags.map((tag, index) => (
|
||||||
<span className="bg-primary/10 text-primary px-3 py-1 rounded-full text-sm">گلکسی بوک</span>
|
<span key={index} className="bg-primary/10 text-primary px-3 py-1 rounded-full text-sm">
|
||||||
<span className="bg-primary/10 text-primary px-3 py-1 rounded-full text-sm">لپتاپ</span>
|
{tag}
|
||||||
<span className="bg-primary/10 text-primary px-3 py-1 rounded-full text-sm">OLED</span>
|
</span>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -104,24 +140,35 @@ const BlogDetail: NextPage = () => {
|
|||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<span className="text-gray-600 font-medium">اشتراکگذاری:</span>
|
<span className="text-gray-600 font-medium">اشتراکگذاری:</span>
|
||||||
<button className="flex items-center gap-2 bg-primary text-white px-4 py-2 rounded-lg hover:bg-primary/90 transition-colors">
|
<button
|
||||||
|
onClick={shareOnTelegram}
|
||||||
|
className="flex items-center gap-2 bg-primary text-white px-4 py-2 rounded-lg hover:bg-primary/90 transition-colors"
|
||||||
|
>
|
||||||
<span>تلگرام</span>
|
<span>تلگرام</span>
|
||||||
</button>
|
</button>
|
||||||
<button className="flex items-center gap-2 bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition-colors">
|
<button
|
||||||
|
onClick={shareOnWhatsApp}
|
||||||
|
className="flex items-center gap-2 bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition-colors"
|
||||||
|
>
|
||||||
<span>واتساپ</span>
|
<span>واتساپ</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
{typeof navigator !== 'undefined' && 'share' in navigator && (
|
||||||
<button className="flex items-center gap-2 text-gray-600 hover:text-red-500 transition-colors">
|
<button
|
||||||
<span>♥</span>
|
onClick={handleNativeShare}
|
||||||
<span>پسندیدن</span>
|
className="flex items-center gap-2 bg-gray-600 text-white px-4 py-2 rounded-lg hover:bg-gray-700 transition-colors"
|
||||||
|
>
|
||||||
|
<Share size={16} color='#ffffff' />
|
||||||
|
<span>اشتراکگذاری</span>
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Sidebar */}
|
{/* Sidebar */}
|
||||||
<div className="w-80 space-y-8">
|
<div className="w-80 space-y-8">
|
||||||
<LastPost blogs={[]} />
|
<LastPost blogs={lastBlogsData?.results?.blogs || []} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as api from "../service/Service";
|
import * as api from "../service/Service";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { BlogResponse, BlogCategory } from "../types/Types";
|
import { BlogResponse, BlogDetailResponse, BlogCategory } from "../types/Types";
|
||||||
|
|
||||||
export const useGetBlogs = (page = 1, limit = 20) => {
|
export const useGetBlogs = (page = 1, limit = 20) => {
|
||||||
return useQuery<BlogResponse>({
|
return useQuery<BlogResponse>({
|
||||||
@@ -17,7 +17,7 @@ export const useGetBlogCategories = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useGetBlogDetails = (id: string) => {
|
export const useGetBlogDetails = (id: string) => {
|
||||||
return useQuery<BlogResponse>({
|
return useQuery<BlogDetailResponse>({
|
||||||
queryKey: ["blog-details", id],
|
queryKey: ["blog-details", id],
|
||||||
queryFn: () => api.getBlogDetails(id),
|
queryFn: () => api.getBlogDetails(id),
|
||||||
enabled: !!id,
|
enabled: !!id,
|
||||||
@@ -35,3 +35,10 @@ export const useGetBlogsByCategory = (
|
|||||||
enabled: !!slug,
|
enabled: !!slug,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useGetLastBlogs = (limit: number = 3) => {
|
||||||
|
return useQuery<BlogResponse>({
|
||||||
|
queryKey: ["last-blogs", limit],
|
||||||
|
queryFn: () => api.getBlogs(1, limit),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import axios from "@/config/axios";
|
import axios from "@/config/axios";
|
||||||
import { BlogResponse, BlogCategory } from "../types/Types";
|
import { BlogResponse, BlogDetailResponse, BlogCategory } from "../types/Types";
|
||||||
|
|
||||||
export const getBlogs = async (
|
export const getBlogs = async (
|
||||||
page: number,
|
page: number,
|
||||||
@@ -19,7 +19,9 @@ export const getBlogCategories = async (): Promise<BlogCategory[]> => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getBlogDetails = async (id: string): Promise<BlogResponse> => {
|
export const getBlogDetails = async (
|
||||||
|
id: string
|
||||||
|
): Promise<BlogDetailResponse> => {
|
||||||
const { data } = await axios.get(`/blogs/${id}`);
|
const { data } = await axios.get(`/blogs/${id}`);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -63,3 +63,11 @@ export interface BlogResponse {
|
|||||||
success: boolean;
|
success: boolean;
|
||||||
results: BlogResults;
|
results: BlogResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface BlogDetailResponse {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
blog: Blog;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user