Shop integration

This commit is contained in:
2026-01-14 17:47:58 +01:00
parent be7f7b7bf7
commit 21b78f8d17
52 changed files with 5288 additions and 198 deletions

View File

@@ -1,95 +1,105 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { motion } from 'framer-motion';
import { JOURNAL_ENTRIES } from '../constants';
import { useStore } from '../src/context/StoreContext';
const Editorial: React.FC = () => {
return (
<div className="bg-white dark:bg-black min-h-screen pt-32 pb-24">
<div className="max-w-[1920px] mx-auto px-6 md:px-12">
<div className="text-center mb-24">
<motion.span
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="font-display text-xs tracking-[0.3em] uppercase mb-4 block text-stone-400"
>
The Journal
</motion.span>
<motion.h1
initial={{ y: 20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ delay: 0.2 }}
className="font-display text-6xl md:text-9xl font-light text-text-main dark:text-white"
>
Editorial
</motion.h1>
</div>
const { articles, isLoading } = useStore();
{/* Featured Article */}
<div className="relative w-full h-[70vh] mb-24 cursor-pointer group overflow-hidden">
<motion.img
initial={{ scale: 1.1 }}
animate={{ scale: 1 }}
transition={{ duration: 1.5 }}
src={JOURNAL_ENTRIES[0].image}
alt="Featured Article"
className="w-full h-full object-cover transition-transform duration-[2s] group-hover:scale-105"
/>
<div className="absolute inset-0 bg-black/20 group-hover:bg-black/40 transition-colors duration-500" />
<div className="absolute bottom-0 left-0 p-8 md:p-16 text-white w-full md:w-2/3">
<span className="uppercase tracking-widest text-xs border border-white/30 px-3 py-1 mb-6 inline-block backdrop-blur-sm">Featured Story</span>
<h2 className="font-display text-4xl md:text-6xl mb-6 leading-tight">{JOURNAL_ENTRIES[0].title}</h2>
<p className="font-body text-lg md:text-xl font-light opacity-90 max-w-xl">{JOURNAL_ENTRIES[0].description}</p>
<div className="mt-8 flex items-center space-x-2 text-xs uppercase tracking-widest">
<span>Read Article</span>
<span className="material-symbols-outlined text-sm">arrow_forward</span>
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>
{/* Article Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-20 max-w-5xl mx-auto">
{JOURNAL_ENTRIES.slice(1).map((entry, idx) => (
<motion.div
key={entry.id}
initial={{ y: 40, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
viewport={{ once: true }}
transition={{ delay: idx * 0.2 }}
className="group cursor-pointer"
>
<div className="aspect-[4/3] overflow-hidden mb-8">
<img src={entry.image} alt={entry.title} className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-105" />
</div>
<div className="flex items-center space-x-4 mb-4 text-xs uppercase tracking-widest text-stone-400">
<span>{entry.category}</span>
<span className="w-1 h-1 bg-stone-300 rounded-full" />
<span>{entry.date}</span>
</div>
<h3 className="font-display text-3xl mb-4 text-text-main dark:text-white group-hover:underline decoration-1 underline-offset-4">{entry.title}</h3>
<p className="font-body font-light text-stone-500">{entry.description}</p>
</motion.div>
))}
{/* Dummy extra entry to fill grid */}
<motion.div
initial={{ y: 40, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
viewport={{ once: true }}
transition={{ delay: 0.4 }}
className="group cursor-pointer"
>
<div className="aspect-[4/3] overflow-hidden mb-8 bg-stone-100 dark:bg-stone-800 flex items-center justify-center">
<img src="/collection-tableware.png" alt="Archive" className="w-full h-full object-cover opacity-80 transition-transform duration-700 group-hover:scale-105" />
</div>
<div className="flex items-center space-x-4 mb-4 text-xs uppercase tracking-widest text-stone-400">
<span>Archive</span>
<span className="w-1 h-1 bg-stone-300 rounded-full" />
<span>2023</span>
</div>
<h3 className="font-display text-3xl mb-4 text-text-main dark:text-white group-hover:underline decoration-1 underline-offset-4">Explore Past Issues</h3>
<p className="font-body font-light text-stone-500">Dive into our archive of stories, guides, and studio updates.</p>
</motion.div>
</div>
</div>
</section>
</div>
);
};