Files
loyalyweb/src/app/blog_main/page.tsx

226 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import React, { useState } from 'react';
import Link from 'next/link';
import Image from 'next/image';
import { useReveal } from '@/hooks/useReveal';
import GSAPAnimator from '@/components/GSAPAnimator';
function Reveal({ children, delay = 0 }: { children: React.ReactNode; delay?: number }) {
const { ref, visible } = useReveal();
return (
<div ref={ref} style={{
opacity: visible ? 1 : 0,
transform: visible ? 'translateY(0)' : 'translateY(48px)',
transition: `opacity 0.9s cubic-bezier(0.22,1,0.36,1) ${delay}s, transform 0.9s cubic-bezier(0.22,1,0.36,1) ${delay}s`,
}}>{children}</div>
);
}
const ARTICLES = [
{
n: '01', tag: 'Analytics', readTime: '6 min',
title: 'Why Footfall Data is the New Gold',
excerpt: "In an era where every click is tracked online, offline retailers are sitting on untapped behavioural gold, and most don't even know it.",
featured: true,
},
{
n: '02', tag: 'Strategy', readTime: '5 min',
title: 'The End of Blind Discounts',
excerpt: "Discounting without data is just burning margin. Here's how AI is changing the way smart retailers think about price reductions.",
featured: false,
},
{
n: '03', tag: 'Technology', readTime: '8 min',
title: 'AI in Offline Retail',
excerpt: 'From footfall heatmaps to purchase prediction, a deep look at how artificial intelligence is rewriting the rules for physical stores.',
featured: false,
},
{
n: '04', tag: 'Growth', readTime: '4 min',
title: 'How to Increase Repeat Customers',
excerpt: 'Acquiring a new customer costs 5× more than retaining one. The playbook for building genuine loyalty in offline retail.',
featured: false,
},
{
n: '05', tag: 'Future', readTime: '7 min',
title: 'The Future of Connected Commerce',
excerpt: 'Online and offline are no longer separate worlds. The retailers who win will be the ones who blur the line completely.',
featured: false,
},
];
const FILTERS = ['All', 'Analytics', 'Strategy', 'Technology', 'Growth', 'Future'];
export default function BlogMainPage() {
const [activeFilter, setActiveFilter] = useState('All');
const [hovered, setHovered] = useState<number | null>(null);
const filtered = activeFilter === 'All' ? ARTICLES : ARTICLES.filter(a => a.tag === activeFilter);
const featured = filtered.find(a => a.featured) || filtered[0];
const rest = filtered.filter(a => a !== featured);
return (
<main style={{ background: '#ffffff', minHeight: '100vh', overflowX: 'hidden' }}>
<GSAPAnimator />
{/* ── HERO ── */}
<section style={{
padding: '120px 8% 100px', background: 'radial-gradient(ellipse 120% 90% at 50% 0%, #2c2350 0%, #211c3e 38%, #181429 100%)',
margin: '20px', borderRadius: '32px',
position: 'relative', overflow: 'hidden',
display: 'flex', alignItems: 'center',
}}>
{/* Background photo */}
<Image src="/images/stock/blog-main.jpg" alt="" fill priority style={{ objectFit: 'cover', opacity: 0.9 }} />
<div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg, rgba(24,20,41,0.1) 0%, rgba(24,20,41,0.55) 85%)' }} />
<div style={{ position: 'absolute', inset: 0, background: 'radial-gradient(ellipse 60% 65% at 50% 48%, rgba(18,14,30,0.78) 0%, rgba(18,14,30,0.35) 60%, transparent 100%)' }} />
{/* Accent blobs */}
<div style={{ position: 'absolute', top: '-14%', left: '6%', width: 480, height: 480, borderRadius: '50%', background: 'radial-gradient(circle, rgba(244,190,40,0.2) 0%, transparent 70%)', pointerEvents: 'none' }} />
<div style={{ position: 'absolute', bottom: '-16%', right: '4%', width: 420, height: 420, borderRadius: '50%', background: 'radial-gradient(circle, rgba(167,139,250,0.18) 0%, transparent 70%)', pointerEvents: 'none' }} />
<div style={{ position: 'absolute', inset: 0, backgroundImage: 'linear-gradient(rgba(244,190,40,0.025) 1px,transparent 1px),linear-gradient(90deg,rgba(244,190,40,0.025) 1px,transparent 1px)', backgroundSize: '60px 60px', pointerEvents: 'none' }} />
<div style={{ position: 'relative', zIndex: 2, width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center' }}>
<div style={{ maxWidth: 720 }}>
<h1 data-gsap="heading" style={{ fontSize: 'clamp(48px, 8vw, 120px)', fontWeight: 800, letterSpacing: '-0.05em', lineHeight: 0.9, color: '#fff', margin: '0 0 28px', fontFamily: 'Sora, sans-serif' }}>
Insights for the<br />
<span style={{ color: '#f4be28' }}>Future of Retail.</span>
</h1>
<p data-gsap="text" style={{ fontSize: 'clamp(16px, 1.5vw, 20px)', lineHeight: 1.75, color: 'rgba(255,255,255,0.55)', fontFamily: 'Sora, sans-serif', maxWidth: 520, margin: '0 auto' }}>
Explore ideas, trends, and strategies shaping modern retail, from our team to yours.
</p>
</div>
</div>
</section>
{/* ── FILTERS ── */}
<section style={{ padding: '48px 8% 0', background: '#fff' }}>
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
{FILTERS.map(f => (
<button key={f} onClick={() => setActiveFilter(f)} style={{
padding: '10px 22px', borderRadius: 100,
background: activeFilter === f ? '#0a0a0f' : 'transparent',
color: activeFilter === f ? '#f4be28' : 'rgba(0,0,0,0.4)',
fontSize: 13, fontWeight: 700, fontFamily: 'Sora, sans-serif',
border: `1px solid ${activeFilter === f ? '#0a0a0f' : 'rgba(0,0,0,0.1)'}`,
cursor: 'pointer', transition: 'all 0.2s ease',
}}>{f}</button>
))}
</div>
</section>
{/* ── FEATURED ARTICLE ── */}
{featured && (
<section style={{ padding: '64px 8%', background: '#fff' }}>
<Reveal>
<div className="bm-featured-grid" style={{
display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '6vw',
padding: '64px', background: '#07070d', borderRadius: 24,
alignItems: 'center', cursor: 'pointer',
transition: 'transform 0.3s ease, box-shadow 0.3s ease',
}}>
{/* Left — article info */}
<div>
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 32 }}>
<span style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: '#f4be28', fontFamily: 'Sora, sans-serif', background: 'rgba(244,190,40,0.1)', padding: '5px 12px', borderRadius: 100, border: '1px solid rgba(244,190,40,0.2)' }}>{featured.tag}</span>
<span style={{ fontSize: 12, color: 'rgba(255,255,255,0.3)', fontFamily: 'Sora, sans-serif' }}>{featured.readTime} read</span>
<span style={{ fontSize: 11, fontWeight: 700, color: '#f4be28', fontFamily: 'Sora, sans-serif', background: 'rgba(244,190,40,0.08)', padding: '4px 10px', borderRadius: 100 }}>Featured</span>
</div>
<h2 style={{ fontSize: 'clamp(28px, 3.5vw, 52px)', fontWeight: 800, letterSpacing: '-0.04em', lineHeight: 1.05, color: '#fff', margin: '0 0 20px', fontFamily: 'Sora, sans-serif' }}>{featured.title}</h2>
<p style={{ fontSize: 16, lineHeight: 1.75, color: 'rgba(255,255,255,0.4)', fontFamily: 'Sora, sans-serif', margin: '0 0 36px' }}>{featured.excerpt}</p>
<Link href="/blog_single_page" style={{ display: 'inline-flex', alignItems: 'center', gap: 8, fontSize: 15, fontWeight: 700, color: '#f4be28', fontFamily: 'Sora, sans-serif', textDecoration: 'none', borderBottom: '1px solid rgba(244,190,40,0.3)', paddingBottom: 4 }}>
Read Article
</Link>
</div>
{/* Right — visual */}
<div style={{
aspectRatio: '4/3', borderRadius: 16,
background: 'linear-gradient(135deg,rgba(244,190,40,0.08) 0%,rgba(244,190,40,0.02) 100%)',
border: '1px solid rgba(244,190,40,0.1)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
position: 'relative', overflow: 'hidden',
}}>
<div style={{
fontSize: 'clamp(80px, 12vw, 160px)', fontWeight: 900,
color: 'transparent', fontFamily: 'Sora, sans-serif',
WebkitTextStroke: '1px rgba(244,190,40,0.15)',
letterSpacing: '-0.06em', lineHeight: 1,
userSelect: 'none',
}}>{featured.n}</div>
</div>
</div>
</Reveal>
</section>
)}
{/* ── ARTICLE GRID ── */}
<section style={{ padding: '0 8% 140px', background: '#fff' }}>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(340px,1fr))', gap: 20 }}>
{rest.map((article, i) => (
<Reveal key={article.n} delay={i * 0.08}>
<div
onMouseEnter={() => setHovered(i)}
onMouseLeave={() => setHovered(null)}
style={{
padding: '40px', borderRadius: 20,
background: '#fff',
border: `1px solid ${hovered === i ? 'rgba(244,190,40,0.3)' : 'rgba(0,0,0,0.08)'}`,
transition: 'all 0.3s cubic-bezier(0.22,1,0.36,1)',
transform: hovered === i ? 'translateY(-6px)' : 'translateY(0)',
boxShadow: hovered === i ? '0 24px 60px rgba(0,0,0,0.1)' : '0 2px 12px rgba(0,0,0,0.04)',
cursor: 'pointer',
display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: 280,
}}
>
<div>
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 24 }}>
<span style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: '#f4be28', fontFamily: 'Sora, sans-serif', background: 'rgba(244,190,40,0.08)', padding: '4px 10px', borderRadius: 100, border: '1px solid rgba(244,190,40,0.15)' }}>{article.tag}</span>
<span style={{ fontSize: 12, color: 'rgba(0,0,0,0.3)', fontFamily: 'Sora, sans-serif' }}>{article.readTime}</span>
</div>
<h3 style={{ fontSize: 'clamp(20px, 2vw, 28px)', fontWeight: 800, letterSpacing: '-0.03em', lineHeight: 1.2, color: '#0a0a0f', margin: '0 0 16px', fontFamily: 'Sora, sans-serif' }}>{article.title}</h3>
<p style={{ fontSize: 14, lineHeight: 1.7, color: 'rgba(0,0,0,0.45)', fontFamily: 'Sora, sans-serif', margin: 0 }}>{article.excerpt}</p>
</div>
<Link href="/blog_single_page" style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 13, fontWeight: 700, color: hovered === i ? '#c9960f' : 'rgba(0,0,0,0.35)', fontFamily: 'Sora, sans-serif', textDecoration: 'none', marginTop: 28, transition: 'color 0.2s' }}>
Read Article
</Link>
</div>
</Reveal>
))}
</div>
</section>
{/* ── NEWSLETTER CTA ── */}
<section style={{ padding: '120px 8%', background: '#07070d', margin: '0 20px 20px', borderRadius: 24, textAlign: 'center', position: 'relative', overflow: 'hidden' }}>
<div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%,-50%)', width: 600, height: 600, borderRadius: '50%', background: 'radial-gradient(circle,rgba(244,190,40,0.06) 0%,transparent 70%)', pointerEvents: 'none' }} />
<Reveal>
<h2 style={{ fontSize: 'clamp(32px, 5vw, 72px)', fontWeight: 800, letterSpacing: '-0.04em', lineHeight: 0.95, color: '#fff', margin: '0 0 20px', fontFamily: 'Sora, sans-serif', position: 'relative', zIndex: 2 }}>
Stay ahead of retail.
</h2>
<p style={{ fontSize: 16, color: 'rgba(255,255,255,0.4)', fontFamily: 'Sora, sans-serif', margin: '0 auto 44px', maxWidth: 400, position: 'relative', zIndex: 2 }}>
Get our latest insights on AI, footfall, and the future of physical retail, delivered monthly.
</p>
<div style={{ display: 'flex', gap: 12, justifyContent: 'center', flexWrap: 'wrap', position: 'relative', zIndex: 2 }}>
<input placeholder="your@email.com" style={{
padding: '16px 24px', borderRadius: 100, border: '1px solid rgba(255,255,255,0.12)',
background: 'rgba(255,255,255,0.06)', color: '#fff',
fontSize: 15, fontFamily: 'Sora, sans-serif', outline: 'none',
backdropFilter: 'blur(12px)', width: 280,
}} />
<button style={{
padding: '16px 32px', borderRadius: 100, border: 'none',
background: '#f4be28', color: '#111',
fontSize: 15, fontWeight: 800, fontFamily: 'Sora, sans-serif', cursor: 'pointer',
}}>Subscribe </button>
</div>
</Reveal>
</section>
<style>{`
@media (max-width: 860px) {
.bm-featured-grid { grid-template-columns: 1fr !important; padding: 36px 28px !important; gap: 36px !important; }
}
`}</style>
</main>
);
}