feat(about): add story sections and core values to About component
Enhance the About page with new story sections detailing personal journey and core values, including icons and structured content for better user engagement and self-presentation.
This commit is contained in:
1 parent
367ca8f495
commit
6ec67c8f5a
11 files changed
+1540
-464
No files matched your search
+239
-72
@@ -2,16 +2,100 @@
|
||||
|
||||
import { motion } from "motion/react";
|
||||
import { BentoGrid, BentoGridItem } from "@/components/magicui/bento-grid";
|
||||
import { ExternalLink, Github } from "lucide-react";
|
||||
import {
|
||||
ExternalLink,
|
||||
Github,
|
||||
Star,
|
||||
Zap,
|
||||
Globe,
|
||||
Cpu,
|
||||
Code2,
|
||||
} from "lucide-react";
|
||||
import { usePortfolioData } from "@/lib/usePortfolioData";
|
||||
|
||||
// Configuração de cores e ícones por categoria
|
||||
const categoryConfig = {
|
||||
"full-stack": {
|
||||
color: "from-blue-500 to-blue-600",
|
||||
bgColor: "bg-blue-500/10",
|
||||
borderColor: "border-blue-500/20",
|
||||
icon: Globe,
|
||||
iconColor: "text-blue-400",
|
||||
},
|
||||
iot: {
|
||||
color: "from-purple-500 to-purple-600",
|
||||
bgColor: "bg-purple-500/10",
|
||||
borderColor: "border-purple-500/20",
|
||||
icon: Cpu,
|
||||
iconColor: "text-purple-400",
|
||||
},
|
||||
api: {
|
||||
color: "from-orange-500 to-orange-600",
|
||||
bgColor: "bg-orange-500/10",
|
||||
borderColor: "border-orange-500/20",
|
||||
icon: Code2,
|
||||
iconColor: "text-orange-400",
|
||||
},
|
||||
web: {
|
||||
color: "from-green-500 to-green-600",
|
||||
bgColor: "bg-green-500/10",
|
||||
borderColor: "border-green-500/20",
|
||||
icon: Globe,
|
||||
iconColor: "text-green-400",
|
||||
},
|
||||
desktop: {
|
||||
color: "from-emerald-500 to-emerald-600",
|
||||
bgColor: "bg-emerald-500/10",
|
||||
borderColor: "border-emerald-500/20",
|
||||
icon: Code2,
|
||||
iconColor: "text-emerald-400",
|
||||
},
|
||||
};
|
||||
|
||||
// Função para gerar estrelas de complexidade
|
||||
const ComplexityStars = ({ complexity }: { complexity: number }) => {
|
||||
return (
|
||||
<div className="flex items-center gap-1">
|
||||
{[...Array(5)].map((_, i) => (
|
||||
<Star
|
||||
key={i}
|
||||
className={`w-3 h-3 ${
|
||||
i < complexity ? "text-yellow-400 fill-yellow-400" : "text-gray-600"
|
||||
}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// Componente de Badge
|
||||
const ProjectBadge = ({ badge, index }: { badge: string; index: number }) => {
|
||||
const badgeColors = [
|
||||
"bg-blue-500/20 text-blue-400 border-blue-500/30",
|
||||
"bg-green-500/20 text-green-400 border-green-500/30",
|
||||
"bg-purple-500/20 text-purple-400 border-purple-500/30",
|
||||
"bg-orange-500/20 text-orange-400 border-orange-500/30",
|
||||
"bg-red-500/20 text-red-400 border-red-500/30",
|
||||
];
|
||||
|
||||
return (
|
||||
<span
|
||||
className={`px-2 py-1 text-xs font-medium rounded-full border ${
|
||||
badgeColors[index % badgeColors.length]
|
||||
}`}
|
||||
>
|
||||
{badge}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export default function Projects() {
|
||||
const { data, loading, error } = usePortfolioData();
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<section id="projects" className="py-20 px-4">
|
||||
<div className="max-w-6xl mx-auto text-center">
|
||||
<div className="max-w-7xl mx-auto text-center">
|
||||
<div className="animate-pulse">
|
||||
<div className="h-8 bg-gray-700 rounded w-1/3 mx-auto mb-4"></div>
|
||||
<div className="h-4 bg-gray-700 rounded w-1/2 mx-auto"></div>
|
||||
@@ -24,7 +108,7 @@ export default function Projects() {
|
||||
if (error || !data) {
|
||||
return (
|
||||
<section id="projects" className="py-20 px-4">
|
||||
<div className="max-w-6xl mx-auto text-center">
|
||||
<div className="max-w-7xl mx-auto text-center">
|
||||
<p className="text-red-400">Erro ao carregar dados de projetos.</p>
|
||||
</div>
|
||||
</section>
|
||||
@@ -35,7 +119,7 @@ export default function Projects() {
|
||||
|
||||
return (
|
||||
<section id="projects" className="py-20 px-4 mx-auto">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
@@ -43,91 +127,174 @@ export default function Projects() {
|
||||
viewport={{ once: true }}
|
||||
className="text-center mb-16"
|
||||
>
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-6">
|
||||
<h2 className="text-4xl md:text-5xl lg:text-6xl font-bold mb-6 bg-gradient-to-r from-cyan-400 to-blue-500 bg-clip-text text-transparent">
|
||||
Projetos em Destaque
|
||||
</h2>
|
||||
<p className="text-xl text-gray-300 max-w-2xl mx-auto">
|
||||
Alguns dos projetos que desenvolvi, demonstrando minhas habilidades
|
||||
e paixão por tecnologia
|
||||
<p className="text-xl text-gray-300 max-w-3xl mx-auto">
|
||||
Uma seleção dos projetos que desenvolvi, demonstrando minha evolução
|
||||
técnica e capacidade de entregar soluções completas em diferentes
|
||||
domínios
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<BentoGrid className="gap-6">
|
||||
{projects.map((project, index) => (
|
||||
<BentoGridItem
|
||||
key={project.id}
|
||||
colSpan={index === 0 ? 2 : 1}
|
||||
className="group hover:scale-[1.02] transition-all duration-300 hover:shadow-2xl hover:shadow-blue-500/10"
|
||||
>
|
||||
<div className="space-y-4">
|
||||
{/* Header */}
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex-1">
|
||||
<h3 className="text-xl font-semibold text-white mb-2">
|
||||
{project.title}
|
||||
</h3>
|
||||
<div className="flex flex-wrap gap-2 mb-3">
|
||||
{project.technologies.map((tech) => (
|
||||
{projects.map((project, index) => {
|
||||
const config =
|
||||
categoryConfig[project.category as keyof typeof categoryConfig] ||
|
||||
categoryConfig["web"];
|
||||
const IconComponent = config.icon;
|
||||
|
||||
return (
|
||||
<BentoGridItem
|
||||
key={project.id}
|
||||
colSpan={index <= 1 ? 2 : 1} // NutriScan e Twins Lab em destaque
|
||||
className={`group hover:scale-105 transition-all duration-300 hover:shadow-2xl ${config.borderColor} border-2 bg-white/5 backdrop-blur-sm`}
|
||||
>
|
||||
<motion.div
|
||||
className="space-y-5 h-full"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: index * 0.1 }}
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
{/* Header com ícone e badges */}
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={`p-3 rounded-xl ${config.bgColor}`}>
|
||||
<IconComponent
|
||||
className={`w-6 h-6 ${config.iconColor}`}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-white mb-1">
|
||||
{project.title}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-400 font-medium">
|
||||
{project.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2">
|
||||
{project.demoUrl && (
|
||||
<a
|
||||
href={project.demoUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="p-2 rounded-lg bg-green-500/20 text-green-400 hover:bg-green-500/30 transition-all duration-300 hover:scale-110"
|
||||
aria-label="Ver demo"
|
||||
>
|
||||
<ExternalLink className="w-4 h-4" />
|
||||
</a>
|
||||
)}
|
||||
{project.githubUrl && (
|
||||
<a
|
||||
href={project.githubUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="p-2 rounded-lg bg-gray-500/20 text-gray-400 hover:bg-gray-500/30 transition-all duration-300 hover:scale-110"
|
||||
aria-label="Ver código"
|
||||
>
|
||||
<Github className="w-4 h-4" />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Badges */}
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{project.badges.map((badge, idx) => (
|
||||
<ProjectBadge key={badge} badge={badge} index={idx} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
<p className="text-gray-300 leading-relaxed text-sm">
|
||||
{project.description}
|
||||
</p>
|
||||
|
||||
{/* Tecnologias principais */}
|
||||
<div>
|
||||
<h4 className="text-xs font-semibold text-gray-400 mb-2 uppercase tracking-wide">
|
||||
Stack Principal
|
||||
</h4>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{project.technologies.slice(0, 4).map((tech) => (
|
||||
<span
|
||||
key={tech}
|
||||
className="px-2 py-1 bg-blue-500/20 text-blue-400 text-xs rounded-full border border-blue-500/30"
|
||||
className="px-2 py-1 bg-gray-800/50 text-gray-300 text-xs rounded border border-gray-700/50"
|
||||
>
|
||||
{tech}
|
||||
</span>
|
||||
))}
|
||||
{project.technologies.length > 4 && (
|
||||
<span className="px-2 py-1 bg-gray-800/30 text-gray-500 text-xs rounded">
|
||||
+{project.technologies.length - 4}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<a
|
||||
href={project.demoUrl}
|
||||
className="p-2 rounded-lg bg-white/10 hover:bg-white/20 transition-colors"
|
||||
aria-label="Ver demo"
|
||||
>
|
||||
<ExternalLink className="w-4 h-4" />
|
||||
</a>
|
||||
<a
|
||||
href={project.githubUrl}
|
||||
className="p-2 rounded-lg bg-white/10 hover:bg-white/20 transition-colors"
|
||||
aria-label="Ver código"
|
||||
>
|
||||
<Github className="w-4 h-4" />
|
||||
</a>
|
||||
|
||||
{/* Features principais */}
|
||||
<div>
|
||||
<h4 className="text-xs font-semibold text-gray-400 mb-2 uppercase tracking-wide">
|
||||
Destaques
|
||||
</h4>
|
||||
<ul className="space-y-1">
|
||||
{project.features.slice(0, 3).map((feature, idx) => (
|
||||
<li
|
||||
key={idx}
|
||||
className="text-xs text-gray-400 flex items-start gap-2"
|
||||
>
|
||||
<Zap className="w-3 h-3 text-yellow-400 mt-0.5 flex-shrink-0" />
|
||||
<span>{feature}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
<p className="text-gray-300 leading-relaxed">
|
||||
{project.description}
|
||||
</p>
|
||||
|
||||
{/* Features */}
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold text-blue-400 mb-2">
|
||||
Funcionalidades:
|
||||
</h4>
|
||||
<ul className="space-y-1">
|
||||
{project.features.map((feature, idx) => (
|
||||
<li
|
||||
key={idx}
|
||||
className="text-sm text-gray-400 flex items-center gap-2"
|
||||
>
|
||||
<div className="w-1.5 h-1.5 bg-blue-400 rounded-full" />
|
||||
{feature}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Status */}
|
||||
<div className="pt-2 border-t border-white/10">
|
||||
<span className="text-xs text-blue-400 font-medium">
|
||||
{project.status}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</BentoGridItem>
|
||||
))}
|
||||
{/* Footer com complexidade e status */}
|
||||
<div className="pt-4 border-t border-white/10 flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs text-gray-500">
|
||||
Complexidade:
|
||||
</span>
|
||||
<ComplexityStars
|
||||
complexity={project.metrics?.complexity || 3}
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
className={`text-xs font-medium px-2 py-1 rounded-full ${
|
||||
project.status === "Em Produção"
|
||||
? "bg-green-500/20 text-green-400 border border-green-500/30"
|
||||
: "bg-blue-500/20 text-blue-400 border border-blue-500/30"
|
||||
}`}
|
||||
>
|
||||
{project.status}
|
||||
</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
</BentoGridItem>
|
||||
);
|
||||
})}
|
||||
</BentoGrid>
|
||||
|
||||
{/* Call to Action */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8, delay: 0.5 }}
|
||||
viewport={{ once: true }}
|
||||
className="text-center mt-16"
|
||||
>
|
||||
<div className="inline-flex items-center gap-2 bg-gradient-to-r from-blue-500/10 to-purple-500/10 px-6 py-3 rounded-full border border-blue-500/20">
|
||||
<div className="w-2 h-2 bg-blue-400 rounded-full animate-pulse"></div>
|
||||
<span className="text-sm text-blue-300 font-medium">
|
||||
Todos os projetos são desenvolvidos individualmente, demonstrando
|
||||
capacidade full-stack completa
|
||||
</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user