214 lines
9.3 KiB
TypeScript
214 lines
9.3 KiB
TypeScript
|
|
import React, { useState, useEffect } from 'react';
|
||
|
|
import { Link } from 'react-router-dom';
|
||
|
|
import { articles } from '../data/articles';
|
||
|
|
import ArticleCard from '../components/ArticleCard';
|
||
|
|
import SEO from '../components/SEO';
|
||
|
|
import { ArrowRight, TrendingUp } from 'lucide-react';
|
||
|
|
import { motion } from 'motion/react';
|
||
|
|
import { useLanguage } from '../contexts/LanguageContext';
|
||
|
|
import { translations } from '../constants';
|
||
|
|
import { Article } from '../types';
|
||
|
|
|
||
|
|
export default function Home() {
|
||
|
|
const { lang, translate } = useLanguage();
|
||
|
|
const t = translations[lang];
|
||
|
|
|
||
|
|
const [displayArticles, setDisplayArticles] = useState<Article[]>(articles);
|
||
|
|
const [loading, setLoading] = useState(false);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
if (lang === 'pt-br') {
|
||
|
|
setDisplayArticles(articles);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const translateHeaders = async () => {
|
||
|
|
setLoading(true);
|
||
|
|
try {
|
||
|
|
// Translate only titles and categories for Home page items
|
||
|
|
const itemsToTranslate = articles.map(a => ({
|
||
|
|
title: a.title,
|
||
|
|
category: a.category
|
||
|
|
}));
|
||
|
|
|
||
|
|
const translatedItems = await translate(itemsToTranslate, 'article titles and categories', true);
|
||
|
|
|
||
|
|
const newArticles = articles.map((a, i) => ({
|
||
|
|
...a,
|
||
|
|
title: translatedItems[i]?.title || a.title,
|
||
|
|
category: translatedItems[i]?.category || a.category
|
||
|
|
}));
|
||
|
|
|
||
|
|
setDisplayArticles(newArticles);
|
||
|
|
} catch (error) {
|
||
|
|
console.error("Home translation error:", error);
|
||
|
|
} finally {
|
||
|
|
setLoading(false);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
translateHeaders();
|
||
|
|
}, [lang, translate]);
|
||
|
|
|
||
|
|
const featuredArticle = displayArticles[0];
|
||
|
|
const recentArticles = displayArticles.slice(1, 4);
|
||
|
|
const secondaryArticles = displayArticles.slice(4, 10);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
<SEO
|
||
|
|
title={t.heroTitle}
|
||
|
|
description={t.heroDescription}
|
||
|
|
/>
|
||
|
|
|
||
|
|
{/* Editorial Hero */}
|
||
|
|
<section className="relative pt-24 pb-20 border-b border-slate-100 bg-white overflow-hidden">
|
||
|
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||
|
|
<div className="max-w-4xl">
|
||
|
|
<motion.div
|
||
|
|
initial={{ opacity: 0 }}
|
||
|
|
animate={{ opacity: 1 }}
|
||
|
|
className="flex items-center gap-3 text-blue-600 font-bold uppercase tracking-[0.3em] text-[9px] mb-8"
|
||
|
|
>
|
||
|
|
<span>{t.heroSubtitle}</span>
|
||
|
|
<div className="h-[1px] w-12 bg-blue-100" />
|
||
|
|
</motion.div>
|
||
|
|
|
||
|
|
<motion.h1
|
||
|
|
initial={{ opacity: 0, y: 30 }}
|
||
|
|
animate={{ opacity: 1, y: 0 }}
|
||
|
|
className="text-6xl sm:text-8xl font-serif font-bold text-slate-950 mb-10 leading-[0.95] tracking-tight"
|
||
|
|
>
|
||
|
|
{lang === 'pt-br' ? (
|
||
|
|
<>A Nova Ordem da <br /><span className="italic font-normal text-blue-600">Busca Semântica.</span></>
|
||
|
|
) : t.heroTitle}
|
||
|
|
</motion.h1>
|
||
|
|
|
||
|
|
<motion.div
|
||
|
|
initial={{ opacity: 0, y: 20 }}
|
||
|
|
animate={{ opacity: 1, y: 0 }}
|
||
|
|
transition={{ delay: 0.1 }}
|
||
|
|
className="flex flex-col sm:flex-row items-start sm:items-center gap-12"
|
||
|
|
>
|
||
|
|
<p className="text-xl text-slate-400 max-w-md leading-relaxed font-medium">
|
||
|
|
{t.heroDescription}
|
||
|
|
</p>
|
||
|
|
<div className="flex flex-col gap-4">
|
||
|
|
<Link
|
||
|
|
to="/sobre"
|
||
|
|
className="px-8 py-4 bg-slate-950 text-white rounded-2xl font-bold text-[10px] uppercase tracking-[0.2em] hover:bg-blue-600 transition-all shadow-xl shadow-slate-200 flex items-center justify-center"
|
||
|
|
>
|
||
|
|
{t.readManifesto}
|
||
|
|
</Link>
|
||
|
|
<div className="flex items-center gap-3">
|
||
|
|
<div className="h-1.5 w-1.5 bg-blue-600 rounded-full animate-ping" />
|
||
|
|
<span className="text-[10px] font-bold text-slate-400 uppercase tracking-widest italic">{t.publishedIn} Maio 2026</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</motion.div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
{/* Featured Insight */}
|
||
|
|
<section className="py-24 bg-[#FCFCFC]">
|
||
|
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||
|
|
<div className="grid grid-cols-1 lg:grid-cols-12 gap-16 items-start">
|
||
|
|
<div className="lg:col-span-8">
|
||
|
|
<div className="flex items-center justify-between mb-8 pb-4 border-b border-slate-200">
|
||
|
|
<h2 className="font-serif text-3xl font-bold italic">{t.recent}</h2>
|
||
|
|
<Link to="/blog" className="text-xs font-bold uppercase tracking-widest text-slate-400 hover:text-slate-950">{t.viewAll}</Link>
|
||
|
|
</div>
|
||
|
|
<ArticleCard article={featuredArticle} featured />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="lg:col-span-4 space-y-12">
|
||
|
|
<div className="bg-slate-950 p-10 rounded-[40px] text-white">
|
||
|
|
<h3 className="text-3xl font-serif font-bold mb-6">{t.newsletterTitle}</h3>
|
||
|
|
<p className="text-slate-400 mb-8 leading-relaxed">
|
||
|
|
{t.newsletterDescription}
|
||
|
|
</p>
|
||
|
|
<form className="space-y-4" onSubmit={(e) => e.preventDefault()}>
|
||
|
|
<input
|
||
|
|
type="email"
|
||
|
|
placeholder={t.emailPlaceholder}
|
||
|
|
className="w-full bg-white/10 border border-white/20 rounded-2xl px-6 py-4 text-white placeholder:text-white/30 focus:outline-none focus:border-white/50"
|
||
|
|
/>
|
||
|
|
<button className="w-full bg-blue-600 hover:bg-blue-500 py-4 rounded-2xl font-bold transition-all">
|
||
|
|
{t.subscribeButton}
|
||
|
|
</button>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<h4 className="font-bold uppercase tracking-widest text-xs text-slate-400 mb-8 pb-4 border-b border-slate-100">{t.trendsTitle}</h4>
|
||
|
|
<div className="space-y-8">
|
||
|
|
{recentArticles.map((article, i) => (
|
||
|
|
<Link key={article.id} to={`/artigo/${article.slug}`} className="group flex gap-4">
|
||
|
|
<span className="font-serif text-3xl italic text-slate-200 font-bold">0{i+1}</span>
|
||
|
|
<div>
|
||
|
|
<h5 className="font-bold text-slate-900 group-hover:text-blue-600 transition-colors leading-snug">
|
||
|
|
{article.title}
|
||
|
|
</h5>
|
||
|
|
<p className="text-xs text-slate-500 mt-2 uppercase font-bold tracking-wider">{article.category}</p>
|
||
|
|
</div>
|
||
|
|
</Link>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
{/* More Insights */}
|
||
|
|
<section className="py-24 bg-white">
|
||
|
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||
|
|
<div className="flex items-center justify-between mb-16 px-4">
|
||
|
|
<h2 className="font-serif text-4xl font-bold">{t.explore}</h2>
|
||
|
|
<Link to="/arquivo" className="h-12 w-12 rounded-full border border-slate-200 flex items-center justify-center hover:border-slate-950 transition-colors">
|
||
|
|
<ArrowRight size={18} />
|
||
|
|
</Link>
|
||
|
|
</div>
|
||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-8 gap-y-16">
|
||
|
|
{secondaryArticles.map(article => (
|
||
|
|
<ArticleCard key={article.id} article={article} />
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
{/* Newsletter Section */}
|
||
|
|
<section id="newsletter" className="py-24 bg-white border-t border-slate-100">
|
||
|
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||
|
|
<div className="bg-slate-950 rounded-[48px] p-10 sm:p-20 text-center text-white relative overflow-hidden">
|
||
|
|
<div className="relative z-10 max-w-2xl mx-auto">
|
||
|
|
<motion.div
|
||
|
|
initial={{ opacity: 0, scale: 0.9 }}
|
||
|
|
whileInView={{ opacity: 1, scale: 1 }}
|
||
|
|
className="inline-flex items-center gap-2 px-3 py-1 bg-white/10 text-white rounded-full text-[10px] font-bold uppercase tracking-widest mb-8"
|
||
|
|
>
|
||
|
|
<span>Editorial VIP</span>
|
||
|
|
</motion.div>
|
||
|
|
<h2 className="text-4xl sm:text-6xl font-serif font-bold mb-8 italic">{t.footerNewsletterTitle}</h2>
|
||
|
|
<p className="text-slate-400 text-lg mb-12">
|
||
|
|
{t.footerNewsletterSubtitle}
|
||
|
|
</p>
|
||
|
|
<form className="flex flex-col sm:flex-row gap-4 max-w-md mx-auto" onSubmit={(e) => e.preventDefault()}>
|
||
|
|
<input
|
||
|
|
type="email"
|
||
|
|
placeholder={t.footerNewsletterInput}
|
||
|
|
className="flex-grow px-8 py-5 rounded-2xl bg-white/5 border border-white/10 text-white focus:outline-none focus:border-blue-600 transition-colors"
|
||
|
|
/>
|
||
|
|
<button className="px-10 py-5 bg-blue-600 text-white rounded-2xl font-bold hover:bg-blue-500 transition-all active:scale-95">
|
||
|
|
{t.subscribe}
|
||
|
|
</button>
|
||
|
|
</form>
|
||
|
|
<p className="mt-8 text-xs text-slate-500 uppercase tracking-widest font-bold">{t.footerNewsletterDisclaimer}</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
</>
|
||
|
|
);
|
||
|
|
}
|