feat: enable project catalog management

This commit is contained in:
Erik
2025-11-27 16:22:14 -03:00
parent f077569bc1
commit 1138747565
6 changed files with 729 additions and 222 deletions

View File

@@ -1,11 +1,49 @@
"use client";
import { useEffect, useState } from "react";
import Link from "next/link";
import { usePageContent } from "@/hooks/usePageContent";
import { useLocale } from "@/contexts/LocaleContext";
type PortfolioProject = {
id: string;
title: string;
category: string;
coverImage: string | null;
galleryImages: string[];
};
type FallbackProject = {
id: string;
title: string;
category: string;
image: string;
};
const FALLBACK_PROJECTS: FallbackProject[] = [
{
id: 'fallback-1',
title: 'Projeto de Adequação - Coca-Cola',
category: 'Engenharia Veicular',
image: 'https://images.unsplash.com/photo-1616401784845-180882ba9ba8?q=80&w=2070&auto=format&fit=crop',
},
{
id: 'fallback-2',
title: 'Laudo de Guindaste Articulado',
category: 'Inspeção Técnica',
image: 'https://images.unsplash.com/photo-1581092335397-9583eb92d232?q=80&w=2070&auto=format&fit=crop',
},
{
id: 'fallback-3',
title: 'Dispositivo de Içamento Especial',
category: 'Projeto Mecânico',
image: 'https://images.unsplash.com/photo-1504917595217-d4dc5ebe6122?q=80&w=2070&auto=format&fit=crop',
},
];
export default function Home() {
const { locale, t } = useLocale();
const [latestProjects, setLatestProjects] = useState<PortfolioProject[]>([]);
// Busca conteúdo JÁ TRADUZIDO do banco (sem tradução em tempo real!)
const { content, loading } = usePageContent('home', locale);
@@ -68,6 +106,35 @@ export default function Home() {
// Prefix para links baseado no locale
const prefix = locale === 'pt' ? '' : `/${locale}`;
useEffect(() => {
let isMounted = true;
const controller = new AbortController();
const fetchProjects = async () => {
try {
const response = await fetch('/api/projects?status=published&take=3', { signal: controller.signal });
if (!response.ok) {
throw new Error('Falha ao buscar projetos mais recentes');
}
const data: PortfolioProject[] = await response.json();
if (isMounted) {
setLatestProjects(data);
}
} catch (err) {
if ((err as Error).name !== 'AbortError') {
console.error('Erro ao buscar projetos recentes:', err);
}
}
};
fetchProjects();
return () => {
isMounted = false;
controller.abort();
};
}, []);
return (
<main className="bg-white dark:bg-secondary transition-colors duration-300">
{/* Hero Section */}
@@ -186,16 +253,20 @@ export default function Home() {
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{[
{ img: "https://images.unsplash.com/photo-1616401784845-180882ba9ba8?q=80&w=2070&auto=format&fit=crop", title: "Projeto de Adequação - Coca-Cola", cat: "Engenharia Veicular" },
{ img: "https://images.unsplash.com/photo-1581092335397-9583eb92d232?q=80&w=2070&auto=format&fit=crop", title: "Laudo de Guindaste Articulado", cat: "Inspeção Técnica" },
{ img: "https://images.unsplash.com/photo-1504917595217-d4dc5ebe6122?q=80&w=2070&auto=format&fit=crop", title: "Dispositivo de Içamento Especial", cat: "Projeto Mecânico" }
].map((project, index) => (
<div key={index} className="group relative overflow-hidden rounded-xl h-[400px] cursor-pointer">
<div className="absolute inset-0 bg-cover bg-center transition-transform duration-500 group-hover:scale-110" style={{ backgroundImage: `url('${project.img}')` }}></div>
{(latestProjects.length > 0
? latestProjects.map((project) => ({
id: project.id,
title: project.title,
category: project.category,
image: project.coverImage || project.galleryImages?.[0] || FALLBACK_PROJECTS[0].image,
}))
: FALLBACK_PROJECTS
).map((project) => (
<div key={project.id} className="group relative overflow-hidden rounded-xl h-[400px] cursor-pointer">
<div className="absolute inset-0 bg-cover bg-center transition-transform duration-500 group-hover:scale-110" style={{ backgroundImage: `url('${project.image}')` }}></div>
<div className="absolute inset-0 bg-linear-to-t from-black/90 via-black/20 to-transparent opacity-80 group-hover:opacity-90 transition-opacity"></div>
<div className="absolute bottom-0 left-0 p-8 w-full transform translate-y-4 group-hover:translate-y-0 transition-transform">
<span className="text-primary font-bold text-sm uppercase tracking-wider mb-2 block">{project.cat}</span>
<span className="text-primary font-bold text-sm uppercase tracking-wider mb-2 block">{project.category}</span>
<h3 className="text-2xl font-bold font-headline text-white mb-2">{project.title}</h3>
<div className="h-0 group-hover:h-auto overflow-hidden transition-all">
<span className="text-white/80 text-sm flex items-center gap-2 mt-4">