feat(cases): cases de clientes, serviços ligados à prova e SEO por página
Cases da SEV Moda Íntima e da Lavação 047; case no formato cliente, problema, entrega, mídia e contato, com detalhes técnicos recolhidos; sem GitHub, ressalvas e fontes de commit. /cases separa clientes e Laboratório. Serviços mostram o case de cliente certo e o bloco de investimento e prazo só aparece preenchido. Metadata social própria por página, not-found com noindex, sitemap com /ia.
This commit is contained in:
1 parent
3756905a1b
commit
6e1022b58c
44 files changed
+2691
-1424
No files matched your search
@@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import { trackCvDownload } from "@/lib/analytics";
|
||||
import { CV_DOWNLOAD_NAME, CV_URL } from "@/lib/site-navigation";
|
||||
|
||||
/** Link do PDF do currículo; mede o clique (só com consentimento de analytics). */
|
||||
export default function CvDownloadLink({
|
||||
className,
|
||||
children,
|
||||
}: {
|
||||
className?: string;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<a
|
||||
className={className}
|
||||
href={CV_URL}
|
||||
download={CV_DOWNLOAD_NAME}
|
||||
onClick={() => trackCvDownload({ placement: "curriculo" })}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
import { render, screen, within } from "@testing-library/react";
|
||||
import { fireEvent, render, screen, within } from "@testing-library/react";
|
||||
import { trackCvDownload } from "@/lib/analytics";
|
||||
import CurriculoPage from "./page";
|
||||
|
||||
jest.mock("@/lib/analytics", () => ({ trackCvDownload: jest.fn() }));
|
||||
|
||||
it("shows a matching breadcrumb and keeps consulting secondary to hiring", () => {
|
||||
render(CurriculoPage());
|
||||
|
||||
@@ -23,3 +26,29 @@ it("shows a matching breadcrumb and keeps consulting secondary to hiring", () =>
|
||||
Node.DOCUMENT_POSITION_FOLLOWING,
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("links to no GitHub profile", () => {
|
||||
render(CurriculoPage());
|
||||
|
||||
// "GitHub Actions" continua como competência técnica; o que não pode haver é endereço do GitHub
|
||||
expect(document.body.textContent).not.toMatch(/github\.com/i);
|
||||
for (const link of screen.getAllByRole("link")) {
|
||||
expect(link.getAttribute("href")).not.toMatch(/github/i);
|
||||
}
|
||||
});
|
||||
|
||||
it("offers the résumé PDF as a secondary action and measures the download", () => {
|
||||
render(CurriculoPage());
|
||||
|
||||
const pdf = screen.getByRole("link", { name: "Baixar currículo em PDF" });
|
||||
expect(pdf).toHaveAttribute("href", "/Profile.pdf");
|
||||
expect(pdf).toHaveAttribute("download", "Evandro_Fonseca_Junior_CV.pdf");
|
||||
// limão só para o contato
|
||||
expect(pdf).not.toHaveClass("ds-link-accent");
|
||||
expect(screen.getByRole("link", { name: /oportunidade/i })).toHaveClass(
|
||||
"ds-link-accent",
|
||||
);
|
||||
|
||||
fireEvent.click(pdf);
|
||||
expect(trackCvDownload).toHaveBeenCalledWith({ placement: "curriculo" });
|
||||
});
|
||||
+24
-33
@@ -1,9 +1,16 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { Breadcrumb } from "@/app/components/Breadcrumb";
|
||||
import { pageTop } from "@/app/components/button-styles";
|
||||
import { safeJsonLd } from "@/lib/jsonld";
|
||||
import { portfolio } from "@/lib/portfolio-data";
|
||||
import { buildBreadcrumbList, buildProfilePageJsonLd } from "@/lib/seo";
|
||||
import {
|
||||
buildBreadcrumbList,
|
||||
buildPageSocialMetadata,
|
||||
buildProfilePageJsonLd,
|
||||
} from "@/lib/seo";
|
||||
import { siteName, siteUrl } from "@/lib/site-content";
|
||||
import CvDownloadLink from "./CvDownloadLink";
|
||||
|
||||
const pageUrl = `${siteUrl}/curriculo`;
|
||||
|
||||
@@ -11,16 +18,13 @@ export const metadata: Metadata = {
|
||||
title: { absolute: `Currículo de Evandro Fonseca Junior | ${siteName}` },
|
||||
description:
|
||||
"Currículo profissional de Evandro Fonseca Junior, engenheiro da computação e desenvolvedor de software, com experiência, formação e competências técnicas.",
|
||||
alternates: { canonical: pageUrl },
|
||||
openGraph: {
|
||||
locale: "pt_BR",
|
||||
...buildPageSocialMetadata({
|
||||
url: pageUrl,
|
||||
title: `Currículo de Evandro Fonseca Junior | ${siteName}`,
|
||||
description:
|
||||
"Experiência profissional, formação e competências técnicas de Evandro Fonseca Junior para avaliação de contratação.",
|
||||
url: pageUrl,
|
||||
siteName,
|
||||
type: "profile",
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
export default function CurriculoPage() {
|
||||
@@ -38,27 +42,14 @@ export default function CurriculoPage() {
|
||||
return (
|
||||
<main>
|
||||
<script type="application/ld+json">{safeJsonLd(jsonLd)}</script>
|
||||
<section className="ds-section ds-section-dark">
|
||||
<section className={`ds-section ds-section-dark ${pageTop}`}>
|
||||
<div className="ds-section-shell max-w-[960px]">
|
||||
<nav aria-label="Breadcrumb" className="mb-sp-6">
|
||||
<ol className="flex flex-wrap items-center gap-sp-2 text-sm">
|
||||
<li>
|
||||
<Link className="ds-link ds-link-muted" href="/">
|
||||
Início
|
||||
</Link>
|
||||
</li>
|
||||
<li className="flex items-center gap-sp-2">
|
||||
<span aria-hidden="true">/</span>
|
||||
<Link
|
||||
aria-current="page"
|
||||
className="ds-link ds-link-muted"
|
||||
href="/curriculo"
|
||||
>
|
||||
Currículo
|
||||
</Link>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<Breadcrumb
|
||||
items={[
|
||||
{ label: "Início", href: "/" },
|
||||
{ label: "Currículo", href: "/curriculo" },
|
||||
]}
|
||||
/>
|
||||
<p className="ds-eyebrow">Currículo profissional</p>
|
||||
<h1 className="ds-section-title text-white">
|
||||
Engenheiro da Computação e Desenvolvedor de Software.
|
||||
@@ -69,13 +60,13 @@ export default function CurriculoPage() {
|
||||
formação e competências técnicas para avaliação de contratação.
|
||||
</p>
|
||||
<div className="mt-sp-6 flex flex-wrap gap-sp-3">
|
||||
<a className="ds-link ds-link-accent" href="/Profile.pdf" download>
|
||||
Baixar currículo em PDF
|
||||
</a>
|
||||
<Link className="ds-link ds-link-muted" href="/#contact">
|
||||
<Link className="ds-link ds-link-accent" href="/#contact">
|
||||
Falar sobre uma oportunidade
|
||||
</Link>
|
||||
<Link className="ds-link ds-link-muted" href="/servicos">
|
||||
<CvDownloadLink className="ds-link ds-link-muted">
|
||||
Baixar currículo em PDF
|
||||
</CvDownloadLink>
|
||||
<Link className="ds-link ds-link-text" href="/servicos">
|
||||
Procurando consultoria? Ver serviços
|
||||
</Link>
|
||||
</div>
|
||||
@@ -131,7 +122,7 @@ export default function CurriculoPage() {
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-sp-8">
|
||||
<Link className="ds-link ds-link-accent" href="/cases">
|
||||
<Link className="ds-link ds-link-muted" href="/cases">
|
||||
Ver projetos e cases
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user