108 lines
6.3 KiB
TypeScript
108 lines
6.3 KiB
TypeScript
import React from 'react';
|
|
import { Link } from 'react-router-dom';
|
|
import { motion } from 'framer-motion';
|
|
import { useStore } from '../src/context/StoreContext';
|
|
|
|
const Editorial: React.FC = () => {
|
|
const { articles, isLoading } = useStore();
|
|
|
|
if (isLoading) return <div className="min-h-screen flex items-center justify-center pt-24 font-light text-stone-400">Loading Journal...</div>;
|
|
if (!articles || articles.length === 0) {
|
|
return (
|
|
<div className="bg-white dark:bg-black min-h-screen pt-32 pb-24 text-center">
|
|
<h1 className="font-display text-4xl mb-8">Editorial</h1>
|
|
<p className="font-body text-stone-500">No stories yet. Stay tuned!</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Sort: Featured first, then rest
|
|
const featuredArticle = articles.find(a => a.isFeatured) || articles[0];
|
|
const otherArticles = articles.filter(a => a.id !== featuredArticle.id);
|
|
|
|
return (
|
|
<div className="min-h-screen pt-32 pb-24 bg-white dark:bg-stone-950 transition-colors duration-500">
|
|
{/* Featured Post */}
|
|
<section className="px-6 mb-32">
|
|
<div className="max-w-[1400px] mx-auto">
|
|
<Link to={`/editorial/${featuredArticle.slug}`} className="group block">
|
|
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12 items-center">
|
|
<div className="lg:col-span-8 overflow-hidden rounded-sm aspect-[16/9]">
|
|
<motion.img
|
|
initial={{ scale: 1.1, opacity: 0 }}
|
|
whileInView={{ scale: 1, opacity: 1 }}
|
|
transition={{ duration: 1.2, ease: [0.22, 1, 0.36, 1] }}
|
|
viewport={{ once: true }}
|
|
src={featuredArticle.image}
|
|
alt={featuredArticle.title}
|
|
className="w-full h-full object-cover grayscale-[0.2] group-hover:grayscale-0 group-hover:scale-105 transition-all duration-700"
|
|
/>
|
|
</div>
|
|
<div className="lg:col-span-4 space-y-6">
|
|
<div className="flex items-center space-x-4">
|
|
<span className="text-[10px] uppercase tracking-[0.3em] text-stone-400">{featuredArticle.category}</span>
|
|
<span className="w-8 h-[1px] bg-stone-200"></span>
|
|
<span className="text-[10px] uppercase tracking-[0.3em] text-stone-400">{featuredArticle.date}</span>
|
|
</div>
|
|
<h2 className="text-4xl md:text-5xl font-light leading-tight tracking-tight text-stone-900 dark:text-stone-100">
|
|
{featuredArticle.title}
|
|
</h2>
|
|
<p className="text-stone-500 font-light leading-relaxed max-w-md">
|
|
{featuredArticle.description}
|
|
</p>
|
|
<div className="pt-4">
|
|
<span className="inline-block text-[10px] uppercase tracking-[0.3em] font-medium border-b border-stone-200 pb-2 group-hover:border-stone-900 transition-colors">
|
|
Read Story
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Other Articles Grid */}
|
|
<section className="px-6">
|
|
<div className="max-w-[1400px] mx-auto">
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-8 gap-y-16">
|
|
{otherArticles.map((entry, idx) => (
|
|
<Link key={entry.id} to={`/editorial/${entry.slug}`} className="group block">
|
|
<motion.div
|
|
initial={{ y: 20, opacity: 0 }}
|
|
whileInView={{ y: 0, opacity: 1 }}
|
|
viewport={{ once: true }}
|
|
transition={{ delay: idx * 0.1 }}
|
|
className="space-y-6"
|
|
>
|
|
<div className="aspect-[4/3] overflow-hidden rounded-sm">
|
|
<img
|
|
src={entry.image}
|
|
alt={entry.title}
|
|
className="w-full h-full object-cover grayscale-[0.2] group-hover:grayscale-0 group-hover:scale-105 transition-all duration-700"
|
|
/>
|
|
</div>
|
|
<div className="space-y-3">
|
|
<div className="flex items-center space-x-4">
|
|
<span className="text-[10px] uppercase tracking-[0.3em] text-stone-400">{entry.category}</span>
|
|
<span className="w-4 h-[1px] bg-stone-200"></span>
|
|
<span className="text-[10px] uppercase tracking-[0.3em] text-stone-400">{entry.date}</span>
|
|
</div>
|
|
<h3 className="text-2xl font-light text-stone-900 dark:text-stone-100 group-hover:text-stone-500 transition-colors">
|
|
{entry.title}
|
|
</h3>
|
|
<p className="text-stone-500 font-light text-sm leading-relaxed line-clamp-2">
|
|
{entry.description}
|
|
</p>
|
|
</div>
|
|
</motion.div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Editorial;
|