feat: rebuild landing experience, content and analytics

This commit is contained in:
Evandro Fonseca Junior committed 2026-09-13 04:30:58 -03:00
1 parent d24ee12299
commit 9aff4d1035
51 files changed
+3023 -2595

No files matched your search

+105 -81
View File
@@ -3,6 +3,7 @@
import { motion, type Variants } from "motion/react";
import { useReducedMotion } from "@/app/hooks/useReducedMotion";
import type { PortfolioProjectView } from "@/lib/portfolio-data";
import { caseStudies } from "@/lib/site-content";
import { DrawLine } from "./animations/DrawLine";
import MagneticButton from "./cinematic/MagneticButton";
import { Section } from "./Section";
@@ -41,9 +42,9 @@ export default function Projects({
return (
<Section
id="projects"
eyebrow="Selected work"
title="Projetos em Next.js, Tauri, Rust e integração de sistemas"
description="Cases e produtos que mostram minha atuação em engenharia de software, consultoria técnica e construção de sistemas de alta exigência."
eyebrow="Projetos"
title="Veja o que já saiu do papel."
description="Sistemas e aplicações com contexto, decisões técnicas e limites documentados. Explore os cases para entender o problema e a solução, além da interface."
dark
disableChildrenAnimation
>
@@ -54,94 +55,117 @@ export default function Projects({
viewport={{ once: true, amount: 0.2 }}
variants={gridVariants}
>
{projects.map((project) => (
<motion.article
key={project.id}
className="ds-card h-full"
variants={cardVariants}
whileHover={
shouldReduceMotion
? undefined
: {
y: -4,
boxShadow: "0 20px 44px rgba(0, 0, 0, 0.42)",
}
}
whileTap={shouldReduceMotion ? undefined : { scale: 0.99 }}
transition={{ type: "spring", stiffness: 170, damping: 18 }}
>
<div className="flex flex-wrap items-start justify-between gap-sp-6">
<div className="max-w-[560px]">
<div className="ds-kicker">{project.category}</div>
<DrawLine delay={0.05} />
<h3 className="ds-card-title">{project.title}</h3>
{project.subtitle && (
<p className="mt-sp-3 text-[13px] leading-6 text-[rgba(255,255,255,.56)]">
{project.subtitle}
</p>
)}
</div>
<MagneticButton
as="span"
className="ds-tag"
strength={0.15}
wrapperClassName="shrink-0 max-sm:ml-auto"
>
{project.status}
</MagneticButton>
</div>
<p className="ds-copy">{project.description}</p>
<ul className="ds-tags mt-sp-6" data-reel-stagger="fade">
{project.technologies.slice(0, 5).map((tech) => (
<li key={tech} className="ds-tag">
{tech}
</li>
))}
</ul>
<div className="mt-sp-6 flex flex-wrap gap-sp-3" data-reel="top">
{project.githubUrl && (
{projects.map((project) => {
const caseStudy = caseStudies.find(
(entry) => entry.id === project.id,
);
return (
<motion.article
key={project.id}
className="ds-card h-full"
variants={cardVariants}
whileHover={
shouldReduceMotion
? undefined
: {
y: -4,
boxShadow: "0 20px 44px rgba(0, 0, 0, 0.42)",
}
}
whileTap={shouldReduceMotion ? undefined : { scale: 0.99 }}
transition={{ type: "spring", stiffness: 170, damping: 18 }}
>
<div className="flex flex-wrap items-start justify-between gap-sp-6">
<div className="max-w-[560px]">
<div className="ds-kicker">{project.category}</div>
<DrawLine delay={0.05} />
<h3 className="ds-card-title">{project.title}</h3>
{project.subtitle && (
<p className="mt-sp-3 text-[13px] leading-6 text-[rgba(255,255,255,.56)]">
{project.subtitle}
</p>
)}
</div>
<MagneticButton
as="a"
href={project.githubUrl}
target="_blank"
rel="noreferrer"
className="ds-link ds-link-muted"
strength={0.25}
as="span"
className="ds-tag"
strength={0.15}
wrapperClassName="shrink-0 max-sm:ml-auto"
>
Ver codigo
{project.status}
</MagneticButton>
</div>
<p className="ds-copy">
{caseStudy?.summary ?? project.description}
</p>
{caseStudy && (
<div className="mt-sp-4 border-l border-[var(--slash)] pl-sp-4">
<p className="ds-kicker">O desafio</p>
<p className="ds-copy">{caseStudy.impact}</p>
</div>
)}
{project.demoUrl &&
(project.demoAvailability === "available" ||
project.demoAvailability === "unknown") && (
<ul className="ds-tags mt-sp-6" data-reel-stagger="fade">
{project.technologies.slice(0, 5).map((tech) => (
<li key={tech} className="ds-tag">
{tech}
</li>
))}
</ul>
<div className="mt-sp-6 flex flex-wrap gap-sp-3" data-reel="top">
{caseStudy && (
<MagneticButton
as="a"
href={project.demoUrl}
target="_blank"
rel="noreferrer"
href={`/cases/${caseStudy.id}`}
className="ds-link ds-link-accent"
strength={0.25}
strength={0.2}
>
Abrir projeto
{project.demoAvailability === "unknown" && (
<span className="sr-only">
{" "}
Disponibilidade não verificada
</span>
)}
Entender a solução
</MagneticButton>
)}
{project.demoAvailability === "unavailable" && (
<span className="ds-link ds-link-accent" aria-disabled="true">
Demo indisponível na última verificação
</span>
)}
</div>
</motion.article>
))}
{project.githubUrl && (
<MagneticButton
as="a"
href={project.githubUrl}
target="_blank"
rel="noreferrer"
className="ds-link ds-link-muted"
strength={0.25}
>
Ver codigo
</MagneticButton>
)}
{project.demoUrl &&
(project.demoAvailability === "available" ||
project.demoAvailability === "unknown") && (
<MagneticButton
as="a"
href={project.demoUrl}
target="_blank"
rel="noreferrer"
className="ds-link ds-link-accent"
strength={0.25}
>
Abrir projeto
{project.demoAvailability === "unknown" && (
<span className="sr-only">
{" "}
Disponibilidade não verificada
</span>
)}
</MagneticButton>
)}
{project.demoAvailability === "unavailable" && (
<span className="ds-link ds-link-accent" aria-disabled="true">
Demo indisponível na última verificação
</span>
)}
</div>
</motion.article>
);
})}
</motion.div>
<div className="mt-sp-8 flex flex-wrap gap-sp-3" data-reel-stagger="left">