ifixkart-storefront/components/blog/BlogViews.tsx

178 lines
5.3 KiB
TypeScript

'use client';
import React, { useMemo, useState } from 'react';
import Link from 'next/link';
import {
BLOG_CATEGORIES,
type BlogArticle,
type BlogCategory,
} from '@/lib/blogDefaults';
function ArticleCard({
article,
featured,
}: {
article: BlogArticle;
featured?: boolean;
}) {
return (
<Link
href={`/blog/${article.slug}`}
className={`group block bg-white border border-gray-200 rounded-xl overflow-hidden hover:border-primary/30 hover:shadow-sm transition-all ${
featured ? '' : ''
}`}
>
<div
className={`relative bg-gray-100 overflow-hidden ${
featured ? 'aspect-[16/8] md:aspect-[16/7]' : 'aspect-[16/10]'
}`}
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={article.image}
alt={article.title}
className="absolute inset-0 w-full h-full object-cover transition-transform duration-500 group-hover:scale-[1.03]"
/>
<span className="absolute top-3 left-3 text-[11px] font-bold uppercase tracking-wide bg-white/95 text-primary px-2 py-1 rounded">
{article.category}
</span>
</div>
<div className={featured ? 'p-5 md:p-6' : 'p-4'}>
<h2
className={`font-bold text-[#1E293B] leading-snug group-hover:text-primary transition-colors ${
featured ? 'text-[20px] md:text-[24px]' : 'text-[15px] line-clamp-2'
}`}
>
{article.title}
</h2>
<p
className={`text-gray-500 mt-2 ${
featured ? 'text-[14px] line-clamp-3' : 'text-[13px] line-clamp-2'
}`}
>
{article.excerpt}
</p>
<p className="text-[12px] text-gray-400 mt-3">
{article.author} · {article.date} · {article.readTime}
</p>
</div>
</Link>
);
}
export function BlogListing({ articles }: { articles: BlogArticle[] }) {
const [category, setCategory] = useState<'All' | BlogCategory>('All');
const filtered = useMemo(
() =>
category === 'All'
? articles
: articles.filter((a) => a.category === category),
[articles, category]
);
const featured = filtered[0];
const rest = filtered.slice(1);
return (
<div>
<h1 className="text-[28px] md:text-[32px] font-bold text-[#1E293B]">
News & Blog
</h1>
<p className="text-[14px] text-gray-500 mt-2 max-w-2xl">
Tech news, buying guides, and repair tips from the iFixKart team.
</p>
<div className="flex flex-wrap gap-2 mt-6 mb-8">
{BLOG_CATEGORIES.map((cat) => {
const active = category === cat;
return (
<button
key={cat}
type="button"
onClick={() => setCategory(cat)}
className={`h-9 px-3.5 rounded-full text-[13px] font-semibold border transition-colors cursor-pointer ${
active
? 'bg-primary text-white border-primary'
: 'bg-white text-gray-600 border-gray-200 hover:border-primary/40 hover:text-primary'
}`}
>
{cat}
</button>
);
})}
</div>
{filtered.length === 0 ? (
<p className="text-[14px] text-gray-500">No articles in this category yet.</p>
) : (
<>
{featured ? <ArticleCard article={featured} featured /> : null}
{rest.length > 0 ? (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 mt-5">
{rest.map((article) => (
<ArticleCard key={article.slug} article={article} />
))}
</div>
) : null}
</>
)}
</div>
);
}
export function BlogArticleView({
article,
related,
}: {
article: BlogArticle;
related: BlogArticle[];
}) {
return (
<article className="max-w-[820px]">
<Link
href="/blog"
className="text-[13px] font-semibold text-primary hover:underline"
>
All articles
</Link>
<span className="ml-3 text-[11px] font-bold uppercase tracking-wide text-primary">
{article.category}
</span>
<h1 className="text-[26px] md:text-[32px] font-bold text-[#1E293B] leading-tight mt-3">
{article.title}
</h1>
<p className="text-[13px] text-gray-500 mt-3">
By {article.author} · {article.date} · {article.readTime}
</p>
<div className="relative w-full aspect-[16/9] rounded-xl overflow-hidden bg-gray-100 mt-6 mb-8">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={article.image}
alt={article.title}
className="absolute inset-0 w-full h-full object-cover"
/>
</div>
<div className="space-y-4">
{article.body.map((para, i) => (
<p key={i} className="text-[15px] text-gray-600 leading-relaxed">
{para}
</p>
))}
</div>
{related.length > 0 ? (
<div className="mt-12 pt-8 border-t border-gray-200">
<h2 className="text-[18px] font-bold text-[#1E293B] mb-4">More stories</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{related.map((item) => (
<ArticleCard key={item.slug} article={item} />
))}
</div>
</div>
) : null}
</article>
);
}