feat(servicos): ofertas no topo de /servicos, capa por assunto e diagramas
/servicos abre com as 3 ofertas e depois outros serviços; H1 de criação de sites e de engenharia com o nome da oferta; capa de cada serviço pelo assunto (SEV fora do próprio case cai de ~11 para 2 imagens); diagrama de fluxo em SVG nos serviços sem case; cases com o que o cliente passou a poder fazer e contato logo depois de Como ficou; FAQ num componente só; lastmod por rota; ProfessionalService com areaServed.
This commit is contained in:
1 parent
e63f3c2ebd
commit
fc44a69fb3
41 files changed
+2486
-550
No files matched your search
@@ -0,0 +1,71 @@
|
||||
import { secondaryButtonLight, textLink } from "@/app/components/button-styles";
|
||||
import HoverPrefetchLink from "@/app/components/HoverPrefetchLink";
|
||||
import {
|
||||
buttonLabels,
|
||||
caseStudies,
|
||||
type ServiceOffer,
|
||||
} from "@/lib/site-content";
|
||||
|
||||
function OfferCard({ offer }: { offer: ServiceOffer }) {
|
||||
const proofCases = offer.proof.caseIds.flatMap((id) => {
|
||||
const caseStudy = caseStudies.find((item) => item.id === id);
|
||||
return caseStudy ? [caseStudy] : [];
|
||||
});
|
||||
|
||||
return (
|
||||
<article className="ds-card">
|
||||
<h3 className="ds-card-title !mt-0 text-balance">{offer.name}</h3>
|
||||
<p className="ds-copy !flex-grow-0">{offer.summary}</p>
|
||||
<ul className="ds-list space-y-sp-2">
|
||||
{offer.deliverables.map((item) => (
|
||||
<li key={item}>{item}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="ds-kicker mt-sp-6">{offer.proof.label}</p>
|
||||
{proofCases.length > 0 ? (
|
||||
<ul className="mt-sp-2 flex flex-wrap gap-x-sp-4">
|
||||
{proofCases.map((caseStudy) => (
|
||||
<li key={caseStudy.id}>
|
||||
<HoverPrefetchLink
|
||||
href={`/cases/${caseStudy.id}`}
|
||||
className={`${textLink} focus-visible:outline-2 focus-visible:outline-offset-4`}
|
||||
>
|
||||
<span className="sr-only">{buttonLabels.case} </span>
|
||||
{caseStudy.title}
|
||||
</HoverPrefetchLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : null}
|
||||
{offer.proof.note ? (
|
||||
<p className="ds-copy !mt-sp-2 !flex-grow-0 text-[15px]">
|
||||
{offer.proof.note}
|
||||
</p>
|
||||
) : null}
|
||||
<div className="mt-sp-6">
|
||||
<HoverPrefetchLink
|
||||
href={offer.href}
|
||||
className={`${secondaryButtonLight} focus-visible:outline-2 focus-visible:outline-offset-4`}
|
||||
>
|
||||
{buttonLabels.service}
|
||||
<span className="sr-only"> {offer.name}</span>
|
||||
</HoverPrefetchLink>
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
|
||||
/** As três ofertas, lado a lado no computador: nome, o que a pessoa recebe, onde ver funcionando e o link da página certa. */
|
||||
export function ServiceOfferCards({
|
||||
offers,
|
||||
}: {
|
||||
offers: readonly ServiceOffer[];
|
||||
}) {
|
||||
return (
|
||||
<div className="mt-sp-8 grid items-stretch gap-sp-6 lg:grid-cols-3">
|
||||
{offers.map((offer) => (
|
||||
<OfferCard key={offer.id} offer={offer} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user