detail blog
This commit is contained in:
+100
-53
@@ -1,16 +1,80 @@
|
||||
'use client'
|
||||
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 { NextPage } from 'next'
|
||||
import Layout from '@/hoc/Layout'
|
||||
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 { 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 (
|
||||
<div className="max-w-7xl mx-auto px-4 py-8">
|
||||
{/* Breadcrumb */}
|
||||
<div className="text-sm text-gray-500 mb-6">
|
||||
فروشگاه {SHOP_CONFIG.name} / راهنما ها / تست اقلام و قطعات / گلکسی بوک
|
||||
فروشگاه {SHOP_CONFIG.name} / {blog.category.title_fa} / {blog.title_fa}
|
||||
</div>
|
||||
|
||||
<div className="flex gap-8">
|
||||
@@ -19,25 +83,25 @@ const BlogDetail: NextPage = () => {
|
||||
{/* Blog Header */}
|
||||
<div className="mb-8">
|
||||
<div className="bg-orange-100 text-orange-600 px-3 py-1 rounded text-sm inline-block mb-4">
|
||||
اخبار
|
||||
{blog.category.title_fa}
|
||||
</div>
|
||||
|
||||
<h1 className="text-2xl font-bold text-gray-900 mb-4 leading-relaxed">
|
||||
مشخصات گلکسی بوک 3 پرو و اولترا پیش از رونمایی فاش شد
|
||||
{blog.title_fa}
|
||||
</h1>
|
||||
|
||||
<div className="flex items-center gap-6 text-gray-500 text-sm">
|
||||
<div className="flex items-center gap-2">
|
||||
<User size={16} color="#9CA3AF" />
|
||||
<span>نویسنده: حمید ضرغامی</span>
|
||||
<span>نویسنده: {blog.author.fullName}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Calendar size={16} color="#9CA3AF" />
|
||||
<span>چهارشنبه 15 آذر 1401 ساعت 15:30</span>
|
||||
<span>{new Date(blog.createdAt).toLocaleDateString('fa-IR')}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Eye size={16} color="#9CA3AF" />
|
||||
<span>1,234 بازدید</span>
|
||||
<span>{blog.view} بازدید</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -45,8 +109,8 @@ const BlogDetail: NextPage = () => {
|
||||
{/* Featured Image */}
|
||||
<div className="mb-8">
|
||||
<Image
|
||||
src="https://images.unsplash.com/photo-1496181133206-80ce9b88a853?w=1200&h=600&fit=crop"
|
||||
alt="Samsung Galaxy Book3 Ultra"
|
||||
src={blog.imageUrl}
|
||||
alt={blog.title_fa}
|
||||
width={1200}
|
||||
height={600}
|
||||
className="w-full h-[400px] object-cover rounded-lg"
|
||||
@@ -54,48 +118,20 @@ const BlogDetail: NextPage = () => {
|
||||
</div>
|
||||
|
||||
{/* Blog Content */}
|
||||
<div className="prose prose-lg max-w-none text-gray-800 leading-8">
|
||||
<p className="text-lg leading-8 mb-6">
|
||||
گلکسی بوک 3 اولترا قویترین عضو این خانواده خواهد بود که با پردازنده نسل سیزدهم اینتل Core i9-13900H، حداکثر 32 گیگابایت رم LPDDR5 و 1 ترابایت حافظه داخلی NVMe PCIe Gen 4 از آن میرسد. این دستگاه همچنین میتواند به حداکثر گرافیک RTX 4070 اویدیا مجهز شود.
|
||||
</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>
|
||||
<div
|
||||
className="prose prose-lg max-w-none text-gray-800 leading-8"
|
||||
dangerouslySetInnerHTML={{ __html: blog.content }}
|
||||
/>
|
||||
|
||||
{/* Tags */}
|
||||
<div className="mt-8 pt-6 border-t border-gray-200">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<span className="text-gray-600 font-medium">برچسبها:</span>
|
||||
<span className="bg-primary/10 text-primary px-3 py-1 rounded-full text-sm">سامسونگ</span>
|
||||
<span className="bg-primary/10 text-primary px-3 py-1 rounded-full text-sm">گلکسی بوک</span>
|
||||
<span className="bg-primary/10 text-primary px-3 py-1 rounded-full text-sm">لپتاپ</span>
|
||||
<span className="bg-primary/10 text-primary px-3 py-1 rounded-full text-sm">OLED</span>
|
||||
{blog.tags.map((tag, index) => (
|
||||
<span key={index} className="bg-primary/10 text-primary px-3 py-1 rounded-full text-sm">
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -104,24 +140,35 @@ const BlogDetail: NextPage = () => {
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<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>
|
||||
</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>
|
||||
</button>
|
||||
</div>
|
||||
<button className="flex items-center gap-2 text-gray-600 hover:text-red-500 transition-colors">
|
||||
<span>♥</span>
|
||||
<span>پسندیدن</span>
|
||||
{typeof navigator !== 'undefined' && 'share' in navigator && (
|
||||
<button
|
||||
onClick={handleNativeShare}
|
||||
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>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
<div className="w-80 space-y-8">
|
||||
<LastPost blogs={[]} />
|
||||
<LastPost blogs={lastBlogsData?.results?.blogs || []} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as api from "../service/Service";
|
||||
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) => {
|
||||
return useQuery<BlogResponse>({
|
||||
@@ -17,7 +17,7 @@ export const useGetBlogCategories = () => {
|
||||
};
|
||||
|
||||
export const useGetBlogDetails = (id: string) => {
|
||||
return useQuery<BlogResponse>({
|
||||
return useQuery<BlogDetailResponse>({
|
||||
queryKey: ["blog-details", id],
|
||||
queryFn: () => api.getBlogDetails(id),
|
||||
enabled: !!id,
|
||||
@@ -35,3 +35,10 @@ export const useGetBlogsByCategory = (
|
||||
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 { BlogResponse, BlogCategory } from "../types/Types";
|
||||
import { BlogResponse, BlogDetailResponse, BlogCategory } from "../types/Types";
|
||||
|
||||
export const getBlogs = async (
|
||||
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}`);
|
||||
return data;
|
||||
};
|
||||
|
||||
@@ -63,3 +63,11 @@ export interface BlogResponse {
|
||||
success: boolean;
|
||||
results: BlogResults;
|
||||
}
|
||||
|
||||
export interface BlogDetailResponse {
|
||||
status: number;
|
||||
success: boolean;
|
||||
results: {
|
||||
blog: Blog;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user