diff --git a/frontend/src/app/(public)/projetos/[id]/page.tsx b/frontend/src/app/(public)/projetos/[id]/page.tsx index 618caa6..b475c8c 100644 --- a/frontend/src/app/(public)/projetos/[id]/page.tsx +++ b/frontend/src/app/(public)/projetos/[id]/page.tsx @@ -1,157 +1,295 @@ +"use client"; + import Link from "next/link"; import { notFound } from "next/navigation"; +import { useState, useEffect } from "react"; +import { T } from "@/components/TranslatedText"; -// Mock data - same as in the main projects page -// In a real app, this would come from a database or API -const projects = [ - { - id: 1, - title: "Engenharia de Adequação - Frota Coca-Cola", - category: "Engenharia Veicular", - location: "Vitória, ES", - image: "https://images.unsplash.com/photo-1616401784845-180882ba9ba8?q=80&w=2070&auto=format&fit=crop", - description: "Projeto de adequação técnica de 50 caminhões para instalação de carrocerias especiais e sistemas de segurança.", - details: "Desenvolvimento completo do projeto de engenharia para adequação de frota de distribuição de bebidas. O escopo incluiu o cálculo estrutural para rebaixamento de carrocerias, instalação de sistemas de proteção lateral e traseira conforme resoluções do CONTRAN, e homologação junto aos órgãos competentes. O projeto resultou em aumento de 15% na capacidade de carga e total conformidade normativa.", - features: ["Cálculo Estrutural", "Homologação DENATRAN", "Segurança Operacional", "Adequação de Carroceria"] - }, - { - id: 2, - title: "Laudo de Guindaste Articulado", - category: "Inspeção Técnica", - location: "Serra, ES", - image: "https://images.unsplash.com/photo-1535082623926-b3a33d531740?q=80&w=2052&auto=format&fit=crop", - description: "Inspeção completa e emissão de laudo técnico para guindaste de 45 toneladas, com testes de carga e verificação estrutural.", - details: "Realização de inspeção detalhada em guindaste articulado (Munck) com capacidade de 45 toneladas. Foram realizados ensaios não destrutivos (líquido penetrante) em pontos críticos de solda, verificação do sistema hidráulico, testes de carga estática e dinâmica conforme NR-11. O laudo técnico atestou a integridade do equipamento para operação segura.", - features: ["Ensaio Não Destrutivo", "Teste de Carga", "Verificação Hidráulica", "ART de Inspeção"] - }, - { - id: 3, - title: "Projeto de Dispositivo de Içamento", - category: "Projeto Mecânico", - location: "Aracruz, ES", - image: "https://images.unsplash.com/photo-1504917595217-d4dc5ebe6122?q=80&w=2070&auto=format&fit=crop", - description: "Desenvolvimento e cálculo estrutural de Spreader para movimentação de contêineres em área portuária.", - details: "Projeto mecânico de um Spreader (balancim) automático para içamento de contêineres de 20 e 40 pés. O dispositivo foi projetado para suportar cargas de até 30 toneladas, com sistema de travamento twist-lock automático. Entregamos o projeto completo em 3D, desenhos de fabricação, memorial de cálculo e manual de operação.", - features: ["Modelagem 3D", "Cálculo de Elementos Finitos", "Detalhamento de Fabricação", "Manual de Operação"] - }, - { - id: 4, - title: "Certificação NR-12 - Parque Industrial", - category: "Laudos", - location: "Linhares, ES", - image: "https://images.unsplash.com/photo-1581092921461-eab62e97a782?q=80&w=2070&auto=format&fit=crop", - description: "Inventário e adequação de segurança de 120 máquinas operatrizes conforme norma regulamentadora NR-12.", - details: "Consultoria completa para adequação à NR-12 em parque fabril. Realizamos o inventário de 120 máquinas, análise de risco (HRN), projeto de proteções mecânicas e sistemas de segurança eletrônica. Acompanhamos a implementação e emitimos os laudos de validação final, garantindo a segurança dos operadores.", - features: ["Análise de Risco", "Projeto de Proteções", "Sistemas de Segurança", "Laudo de Validação"] - }, - { - id: 5, - title: "Homologação de Plataforma Elevatória", - category: "Engenharia Veicular", - location: "Viana, ES", - image: "https://images.unsplash.com/photo-1591768793355-74d04bb6608f?q=80&w=2070&auto=format&fit=crop", - description: "Processo completo de homologação e certificação de plataformas elevatórias para distribuição urbana.", - details: "Assessoria técnica para fabricante de plataformas elevatórias veiculares. Realizamos os cálculos de estabilidade, testes de tombamento e resistência estrutural necessários para a obtenção do CAT (Certificado de Adequação à Legislação de Trânsito). O equipamento foi homologado com sucesso para uso em veículos urbanos de carga.", - features: ["Cálculo de Estabilidade", "Teste de Tombamento", "Dossiê Técnico", "Homologação INMETRO/DENATRAN"] - }, - { - id: 6, - title: "Projeto de Linha de Vida para Caminhões", - category: "Segurança do Trabalho", - location: "Cariacica, ES", - image: "https://images.unsplash.com/photo-1504328345606-18bbc8c9d7d1?q=80&w=2070&auto=format&fit=crop", - description: "Projeto e instalação de sistema de linha de vida para proteção contra quedas em operações de carga e descarga.", - details: "Projeto e instalação de sistema de linha de vida rígida sobre estrutura metálica para proteção de quedas durante o enlonamento de caminhões. O sistema permite que o operador trabalhe com segurança em toda a extensão da carroceria. Fornecimento de projeto, ART e treinamento de uso para a equipe.", - features: ["Projeto Estrutural", "Sistema de Ancoragem", "Treinamento NR-35", "ART de Instalação"] - } -]; +interface Project { + id: string; + title: string; + category: string; + client: string | null; + status: string; + completionDate: string | null; + description: string | null; + coverImage: string | null; + galleryImages: string[]; + featured: boolean; + createdAt: string; +} export default function ProjectDetails({ params }: { params: { id: string } }) { - const project = projects.find((p) => p.id === parseInt(params.id)); + const [project, setProject] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); + const [selectedImage, setSelectedImage] = useState(null); + const [lightboxOpen, setLightboxOpen] = useState(false); - if (!project) { + useEffect(() => { + async function fetchProject() { + try { + const res = await fetch(`/api/projects/${params.id}`, { cache: "no-store" }); + if (res.ok) { + const data = await res.json(); + setProject(data); + setSelectedImage(data.coverImage || data.galleryImages?.[0] || null); + } else if (res.status === 404) { + setError(true); + } + } catch (err) { + console.error("Erro ao carregar projeto:", err); + setError(true); + } finally { + setLoading(false); + } + } + fetchProject(); + }, [params.id]); + + if (loading) { + return ( +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ); + } + + if (error || !project) { notFound(); } + const defaultImage = "https://images.unsplash.com/photo-1504307651254-35680f356dfd?q=80&w=2070&auto=format&fit=crop"; + const heroImage = project.coverImage || defaultImage; + const allImages = [ + ...(project.coverImage ? [project.coverImage] : []), + ...project.galleryImages, + ].filter(Boolean); + + const completionYear = project.completionDate + ? new Date(project.completionDate).getFullYear() + : new Date(project.createdAt).getFullYear(); + return ( -
+
{/* Hero Section */}
- - {project.category} - + {project.category && ( + + {project.category} + + )}

{project.title}

-
- - {project.location} +
+ {project.client && ( +
+ + {project.client} +
+ )} +
+ + {completionYear} +
+
+ + {project.status} + +
{/* Content Section */} -
+
{/* Main Content */}
-

Sobre o Projeto

-

- {project.details} -

- -

Escopo Técnico

-
- {project.features.map((feature, index) => ( -
- - {feature} + {/* Description */} + {project.description && ( + <> +

+ Sobre o Projeto +

+

+ {project.description} +

+ + )} + + {/* Image Gallery */} + {allImages.length > 0 && ( + <> +

+ Galeria de Imagens +

+ + {/* Main Image */} +
{ + setLightboxOpen(true); + }} + > + {project.title} +
+ +
- ))} -
+ + {/* Thumbnail Grid */} + {allImages.length > 1 && ( +
+ {allImages.map((img, index) => ( + + ))} +
+ )} + + )}
{/* Sidebar */}
-
-

Ficha Técnica

+
+

+ Ficha Técnica +

    -
  • - Cliente - Confidencial + {project.client && ( +
  • + Cliente + {project.client} +
  • + )} + {project.category && ( +
  • + Categoria + {project.category} +
  • + )} +
  • + Status + + {project.status} +
  • -
  • - Categoria - {project.category} -
  • -
  • - Local - {project.location} -
  • -
  • - Ano - 2024 +
  • + Ano + {completionYear}
  • + {project.featured && ( +
  • + Destaque + + Sim + +
  • + )}
- - Solicitar Orçamento Similar + + Solicitar Orçamento Similar - - Voltar para Projetos + + Voltar para Projetos
+ + {/* Lightbox */} + {lightboxOpen && ( +
setLightboxOpen(false)} + > + + + {allImages.length > 1 && ( + <> + + + + )} + + {project.title} e.stopPropagation()} + /> +
+ )}
); } diff --git a/frontend/src/app/[locale]/projetos/[id]/page.tsx b/frontend/src/app/[locale]/projetos/[id]/page.tsx new file mode 100644 index 0000000..fc790aa --- /dev/null +++ b/frontend/src/app/[locale]/projetos/[id]/page.tsx @@ -0,0 +1,317 @@ +"use client"; + +import Link from "next/link"; +import { notFound } from "next/navigation"; +import { useState, useEffect } from "react"; +import { useLocale } from "@/contexts/LocaleContext"; + +interface Project { + id: string; + title: string; + category: string; + client: string | null; + status: string; + completionDate: string | null; + description: string | null; + coverImage: string | null; + galleryImages: string[]; + featured: boolean; + createdAt: string; +} + +export default function ProjectDetails({ params }: { params: { id: string; locale: string } }) { + const { t, locale } = useLocale(); + const prefix = locale === 'pt' ? '' : `/${locale}`; + + const [project, setProject] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); + const [selectedImage, setSelectedImage] = useState(null); + const [lightboxOpen, setLightboxOpen] = useState(false); + + // Translations + const texts = { + aboutProject: locale === 'pt' ? 'Sobre o Projeto' : locale === 'es' ? 'Sobre el Proyecto' : 'About the Project', + imageGallery: locale === 'pt' ? 'Galeria de Imagens' : locale === 'es' ? 'Galería de Imágenes' : 'Image Gallery', + technicalSheet: locale === 'pt' ? 'Ficha Técnica' : locale === 'es' ? 'Ficha Técnica' : 'Technical Sheet', + client: locale === 'pt' ? 'Cliente' : locale === 'es' ? 'Cliente' : 'Client', + category: locale === 'pt' ? 'Categoria' : locale === 'es' ? 'Categoría' : 'Category', + status: locale === 'pt' ? 'Status' : locale === 'es' ? 'Estado' : 'Status', + year: locale === 'pt' ? 'Ano' : locale === 'es' ? 'Año' : 'Year', + featured: locale === 'pt' ? 'Destaque' : locale === 'es' ? 'Destacado' : 'Featured', + yes: locale === 'pt' ? 'Sim' : locale === 'es' ? 'Sí' : 'Yes', + requestQuote: locale === 'pt' ? 'Solicitar Orçamento Similar' : locale === 'es' ? 'Solicitar Presupuesto Similar' : 'Request Similar Quote', + backToProjects: locale === 'pt' ? 'Voltar para Projetos' : locale === 'es' ? 'Volver a Proyectos' : 'Back to Projects', + completed: locale === 'pt' ? 'Concluído' : locale === 'es' ? 'Completado' : 'Completed', + inProgress: locale === 'pt' ? 'Em andamento' : locale === 'es' ? 'En progreso' : 'In Progress', + }; + + useEffect(() => { + async function fetchProject() { + try { + const res = await fetch(`/api/projects/${params.id}`, { cache: "no-store" }); + if (res.ok) { + const data = await res.json(); + setProject(data); + setSelectedImage(data.coverImage || data.galleryImages?.[0] || null); + } else if (res.status === 404) { + setError(true); + } + } catch (err) { + console.error("Erro ao carregar projeto:", err); + setError(true); + } finally { + setLoading(false); + } + } + fetchProject(); + }, [params.id]); + + if (loading) { + return ( +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ); + } + + if (error || !project) { + notFound(); + } + + const defaultImage = "https://images.unsplash.com/photo-1504307651254-35680f356dfd?q=80&w=2070&auto=format&fit=crop"; + const heroImage = project.coverImage || defaultImage; + const allImages = [ + ...(project.coverImage ? [project.coverImage] : []), + ...project.galleryImages, + ].filter(Boolean); + + const completionYear = project.completionDate + ? new Date(project.completionDate).getFullYear() + : new Date(project.createdAt).getFullYear(); + + const statusText = project.status === 'Concluído' ? texts.completed : texts.inProgress; + + return ( +
+ {/* Hero Section */} +
+
+
+
+ {project.category && ( + + {project.category} + + )} +

+ {project.title} +

+
+ {project.client && ( +
+ + {project.client} +
+ )} +
+ + {completionYear} +
+
+ + {statusText} + +
+
+
+
+ + {/* Content Section */} +
+
+
+ {/* Main Content */} +
+ {/* Description */} + {project.description && ( + <> +

+ {texts.aboutProject} +

+

+ {project.description} +

+ + )} + + {/* Image Gallery */} + {allImages.length > 0 && ( + <> +

+ {texts.imageGallery} +

+ + {/* Main Image */} +
{ + setLightboxOpen(true); + }} + > + {project.title} +
+ +
+
+ + {/* Thumbnail Grid */} + {allImages.length > 1 && ( +
+ {allImages.map((img, index) => ( + + ))} +
+ )} + + )} +
+ + {/* Sidebar */} +
+
+

+ {texts.technicalSheet} +

+
    + {project.client && ( +
  • + {texts.client} + {project.client} +
  • + )} + {project.category && ( +
  • + {texts.category} + {project.category} +
  • + )} +
  • + {texts.status} + + {statusText} + +
  • +
  • + {texts.year} + {completionYear} +
  • + {project.featured && ( +
  • + {texts.featured} + + {texts.yes} + +
  • + )} +
+ + + {texts.requestQuote} + + + {texts.backToProjects} + +
+
+
+
+
+ + {/* Lightbox */} + {lightboxOpen && ( +
setLightboxOpen(false)} + > + + + {allImages.length > 1 && ( + <> + + + + )} + + {project.title} e.stopPropagation()} + /> +
+ )} +
+ ); +}