S SmartDocs
Série: vibe coding javascript 123 linhas · Atualizado 2026-04-26

ProjectDetail.jsx

vibe_coding/src/pages/ProjectDetail.jsx

import { useParams, Link, useNavigate } from 'react-router-dom';
import { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { getProjectBySlug, getNeighbours } from '../data/projects.js';

export default function ProjectDetail() {
  const { slug } = useParams();
  const { t, i18n } = useTranslation();
  const navigate = useNavigate();
  const project = getProjectBySlug(slug);

  useEffect(() => {
    if (!project) navigate('/proyectos', { replace: true });
  }, [project, navigate]);

  if (!project) return null;

  const lang = (i18n.resolvedLanguage || 'es').slice(0, 2);
  const fallback = (obj) => (obj?.[lang] ?? obj?.es ?? '');

  const { prev, next } = getNeighbours(project.slug);
  const gallery = project.gallery || [];

  return (
    <article>
      <section className="proj-hero">
        {project.cover ? (
          <img
            src={project.cover}
            alt={fallback(project.title)}
            style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover' }}
          />
        ) : (
          <div className="placeholder">{fallback(project.title)}</div>
        )}
        <div className="proj-hero__inner">
          <span className="hero__tag">{t(`projects.tags.${project.type}`)}</span>
          <h1>{fallback(project.title)}</h1>
          <p>{fallback(project.summary)}</p>
        </div>
      </section>

      <div className="container--narrow">
        <dl className="proj-meta">
          <div>
            <dt>{t('projects.detail.type')}</dt>
            <dd>{fallback(project.meta?.type)}</dd>
          </div>
          <div>
            <dt>{t('projects.detail.area')}</dt>
            <dd>{fallback(project.meta?.area)}</dd>
          </div>
          <div>
            <dt>{t('projects.detail.year')}</dt>
            <dd>{fallback(project.meta?.year)}</dd>
          </div>
          <div>
            <dt>{t('projects.detail.location')}</dt>
            <dd>{fallback(project.meta?.location)}</dd>
          </div>
        </dl>

        <blockquote className="proj-question">
          {t('projects.detail.question')}
          <br />
          <span style={{ color: 'var(--color-text)', fontSize: '0.9em' }}>
            — {fallback(project.question)}
          </span>
        </blockquote>

        <section className="proj-section">
          <span className="eyebrow">{t('projects.detail.process')}</span>
          <h3>{t('projects.detail.process')}</h3>
          <div className="proj-gallery">
            {gallery.length === 0 ? (
              <>
                <div className="placeholder">Sketch</div>
                <div className="placeholder">Plan</div>
                <div className="placeholder">Render</div>
                <div className="placeholder">Detail</div>
              </>
            ) : (
              gallery.map((g, i) => (
                <div
                  key={i}
                  className={`placeholder ${g.kind === 'tall' ? 'tall' : ''}`}
                >
                  {g.label || `0${i + 1}`}
                </div>
              ))
            )}
          </div>
        </section>

        <section className="proj-section">
          <span className="eyebrow">{t('projects.detail.description')}</span>
          <h3>{t('projects.detail.description')}</h3>
          <p>{fallback(project.description)}</p>
        </section>

        <section className="proj-section">
          <span className="eyebrow">{t('projects.detail.materials')}</span>
          <h3>{t('projects.detail.materials')}</h3>
          <p>{fallback(project.materials)}</p>
        </section>

        <nav className="proj-nav">
          {prev ? (
            <Link to={`/proyectos/${prev.slug}`}>← {t('projects.detail.prev')}</Link>
          ) : (
            <span />
          )}
          <Link to="/proyectos">{t('projects.detail.back')}</Link>
          {next ? (
            <Link to={`/proyectos/${next.slug}`}>{t('projects.detail.next')} →</Link>
          ) : (
            <span />
          )}
        </nav>
      </div>
    </article>
  );
}

Artigos relacionados