This commit initializes the project with a basic Next.js setup, including: - Integration of `tailwindcss` and `tw-animate-css` for styling. - Definition of a comprehensive color palette using CSS variables for both light and dark themes, supporting a theming system. - Implementation of a custom `aurora` keyframe animation. - Configuration of global CSS styles for `border` and `body` elements. - Setup of `next.config.ts` with image optimization, performance enhancements, and security headers (X-Frame-Options, X-Content-Type-Options, Referrer-Policy). - Update of `package.json` to include new dependencies for UI components (`class-variance-authority`, `clsx`, `lucide-react`, `motion`, `tailwind-merge`, `tailwindcss-animate`) and development tools (`@biomejs/biome`, `@tailwindcss/postcss`, `tw-animate-css`). - Refinement of `app/layout.tsx` to include comprehensive metadata for SEO (title, description, keywords, authors, Open Graph, Twitter cards, robots), preconnect/dns-prefetch links for external resources, favicon, manifest, and mobile app meta tags. - Restructuring of `app/page.tsx` to use dynamic imports for various sections (Hero, About, Skills, Experience, Projects, Contact, WorkModalities) to improve performance, and integration of `Squares` component for background effects. This foundational commit prepares the application for further development by establishing a robust and performant base.
91 lines
3.3 KiB
TypeScript
91 lines
3.3 KiB
TypeScript
"use client";
|
|
|
|
import { motion } from "motion/react";
|
|
import { ShimmerButton } from "@/components/magicui/shimmer-button";
|
|
import { useRef, useState } from "react";
|
|
import { usePortfolioData } from "@/lib/usePortfolioData";
|
|
import { ContactForm } from "./ContactForm"; // Importar o novo componente
|
|
import { ContactInfo } from "./ContactInfo"; // Importar o novo componente
|
|
|
|
export default function Contact() {
|
|
const { data } = usePortfolioData();
|
|
const contactSectionRef = useRef<HTMLElement>(null);
|
|
const [formType, setFormType] = useState<"simple" | "advanced">("simple"); // Estado para controlar o tipo de formulário
|
|
|
|
const handleWhatsAppClick = () => {
|
|
setFormType("simple"); // Redireciona para o formulário simples
|
|
if (contactSectionRef.current) {
|
|
contactSectionRef.current.scrollIntoView({ behavior: "smooth" });
|
|
}
|
|
};
|
|
|
|
const scrollToContact = () => {
|
|
if (contactSectionRef.current) {
|
|
contactSectionRef.current.scrollIntoView({ behavior: "smooth" });
|
|
}
|
|
};
|
|
|
|
if (!data) {
|
|
return null; // Ou um componente de carregamento/erro
|
|
}
|
|
|
|
return (
|
|
<section
|
|
id="contact"
|
|
ref={contactSectionRef}
|
|
className="py-20 px-4 bg-gradient-to-t from-black/20 to-transparent"
|
|
>
|
|
<div className="max-w-6xl mx-auto">
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 30 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.8 }}
|
|
viewport={{ once: true }}
|
|
className="text-center mb-16"
|
|
>
|
|
<h2 className="text-4xl md:text-5xl font-bold mb-6">
|
|
Vamos Conversar
|
|
</h2>
|
|
<p className="text-xl text-gray-300 max-w-2xl mx-auto">
|
|
Estou sempre interessado em novos desafios e oportunidades. Vamos
|
|
discutir como posso ajudar seu projeto?
|
|
</p>
|
|
</motion.div>
|
|
|
|
<div className="grid md:grid-cols-2 gap-8 items-start mt-16">
|
|
{/* Contact Info */}
|
|
<ContactInfo onWhatsAppClick={handleWhatsAppClick} />
|
|
|
|
{/* Contact Options and Map */}
|
|
<div className="flex flex-col gap-8">
|
|
<ContactForm formType={formType} setFormType={setFormType} />{" "}
|
|
{/* Usar o novo componente ContactForm */}
|
|
{/* Mapa */}
|
|
<motion.div
|
|
initial={{ opacity: 0, x: 30 }}
|
|
whileInView={{ opacity: 1, x: 0 }}
|
|
transition={{ duration: 0.8, delay: 0.6 }}
|
|
viewport={{ once: true }}
|
|
>
|
|
<h3 className="text-2xl font-semibold mb-4 text-blue-400">
|
|
Onde me encontrar
|
|
</h3>
|
|
<div className="overflow-hidden rounded-lg shadow-lg">
|
|
<iframe
|
|
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3557.1999999999996!2d-48.77891484804123!3d-26.087801635807004!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x0!2zMjbCsDA1JzE2LjEiUyA0OMKwNDYnNDQuMSJX!5e0!3m2!1spt-BR!2sbr!4v1700000000000!5m2!1spt-BR!2sbr"
|
|
width="100%"
|
|
height="450"
|
|
style={{ border: 0 }}
|
|
allowFullScreen={true}
|
|
loading="lazy"
|
|
referrerPolicy="no-referrer-when-downgrade"
|
|
></iframe>
|
|
</div>
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|