Versão inicial do site Avanzato

This commit is contained in:
2026-05-25 23:31:32 -03:00
commit 4eed31a206
155 changed files with 31304 additions and 0 deletions
+257
View File
@@ -0,0 +1,257 @@
import { useEffect, useRef, useState } from 'react';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { Check, Award, Users, Clock } from 'lucide-react';
gsap.registerPlugin(ScrollTrigger);
interface CounterProps {
end: number;
suffix?: string;
prefix?: string;
duration?: number;
}
const Counter = ({ end, suffix = '', prefix = '', duration = 2 }: CounterProps) => {
const [count, setCount] = useState(0);
const counterRef = useRef<HTMLDivElement>(null);
const hasAnimated = useRef(false);
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting && !hasAnimated.current) {
hasAnimated.current = true;
let startTime: number;
const animate = (timestamp: number) => {
if (!startTime) startTime = timestamp;
const progress = Math.min((timestamp - startTime) / (duration * 1000), 1);
setCount(Math.floor(progress * end));
if (progress < 1) {
requestAnimationFrame(animate);
}
};
requestAnimationFrame(animate);
}
});
},
{ threshold: 0.5 }
);
if (counterRef.current) {
observer.observe(counterRef.current);
}
return () => observer.disconnect();
}, [end, duration]);
return (
<div ref={counterRef} className="counter text-4xl md:text-5xl font-black text-[#cbf400]">
{prefix}{count}{suffix}
</div>
);
};
const About = () => {
const sectionRef = useRef<HTMLDivElement>(null);
const imageRef = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null);
const statsRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const ctx = gsap.context(() => {
// Image reveal animation
gsap.fromTo(
imageRef.current,
{ clipPath: 'circle(0% at 50% 50%)', opacity: 0 },
{
clipPath: 'circle(100% at 50% 50%)',
opacity: 1,
duration: 1.2,
ease: 'power3.out',
scrollTrigger: {
trigger: imageRef.current,
start: 'top 80%',
toggleActions: 'play none none reverse',
},
}
);
// Content animation
const contentElements = contentRef.current?.querySelectorAll('.animate-item');
if (contentElements) {
gsap.fromTo(
contentElements,
{ y: 30, opacity: 0 },
{
y: 0,
opacity: 1,
duration: 0.6,
stagger: 0.1,
ease: 'back.out(1.7)',
scrollTrigger: {
trigger: contentRef.current,
start: 'top 80%',
toggleActions: 'play none none reverse',
},
}
);
}
// Stats animation
gsap.fromTo(
statsRef.current,
{ y: 50, opacity: 0 },
{
y: 0,
opacity: 1,
duration: 0.8,
ease: 'expo.out',
scrollTrigger: {
trigger: statsRef.current,
start: 'top 85%',
toggleActions: 'play none none reverse',
},
}
);
}, sectionRef);
return () => ctx.revert();
}, []);
const differentials = [
'Atendimento personalizado e próximo',
'Equipe certificada e especializada',
'SLA garantido em todos os serviços',
'Tecnologia de ponta sempre atualizada',
'Relatórios detalhados e transparentes',
'Foco em resultados e produtividade',
];
return (
<section
id="about"
ref={sectionRef}
className="section-padding bg-[#1a1a1a] relative overflow-hidden"
>
{/* Background decoration */}
<div className="absolute top-1/2 left-0 w-[600px] h-[600px] bg-[#cbf400]/5 rounded-full blur-3xl -translate-y-1/2 -translate-x-1/2" />
<div className="container-custom relative z-10">
<div className="grid lg:grid-cols-2 gap-12 lg:gap-20 items-center">
{/* Image */}
<div ref={imageRef} className="relative">
<div className="relative rounded-2xl overflow-hidden shadow-2xl border border-white/5">
<img
src="/about-image.jpg"
alt="Equipe Avanzato"
className="w-full h-auto object-cover"
/>
{/* Glassmorphism overlay card */}
<div className="absolute bottom-6 left-6 right-6 glass rounded-xl p-6 border border-[#cbf400]/20">
<div className="flex items-center gap-4">
<div className="w-14 h-14 rounded-full bg-[#cbf400]/20 flex items-center justify-center border border-[#cbf400]/30">
<Award className="w-7 h-7 text-[#cbf400]" />
</div>
<div>
<div className="text-white font-bold text-lg">+23 anos</div>
<div className="text-gray-400 text-sm">de experiência no mercado</div>
</div>
</div>
</div>
</div>
{/* Decorative elements */}
<div className="absolute -top-4 -right-4 w-24 h-24 border-2 border-[#cbf400]/20 rounded-xl" />
<div className="absolute -bottom-4 -left-4 w-32 h-32 bg-[#cbf400]/10 rounded-xl -z-10" />
</div>
{/* Content */}
<div ref={contentRef}>
<span className="animate-item inline-block px-4 py-2 rounded-full bg-[#cbf400]/10 text-[#cbf400] text-sm font-semibold mb-4 border border-[#cbf400]/20">
Sobre a Avanzato
</span>
<h2 className="animate-item text-3xl md:text-4xl lg:text-5xl font-black text-white mb-6">
Por que escolher a{' '}
<span className="text-gradient">Avanzato?</span>
</h2>
<p className="animate-item text-gray-400 text-lg mb-6 leading-relaxed">
Com mais de 23 anos de experiência, somos o parceiro estratégico que sua empresa
precisa para navegar na transformação digital. Não vendemos tecnologia,
<strong className="text-white"> entregamos resultados</strong>.
</p>
<p className="animate-item text-gray-400 mb-8 leading-relaxed">
Nossa missão é capacitar empresas de todos os tamanhos a alcançar seus objetivos,
assegurando que a TI seja uma aliada estratégica. Permitimos que nossos clientes
se concentrem no que fazem de melhor - conduzir seus negócios com sucesso.
</p>
{/* Differentials */}
<div className="animate-item grid sm:grid-cols-2 gap-3 mb-8">
{differentials.map((item, index) => (
<div key={index} className="flex items-start gap-3">
<div className="w-5 h-5 rounded-full bg-[#cbf400]/10 flex items-center justify-center flex-shrink-0 mt-0.5 border border-[#cbf400]/30">
<Check className="w-3 h-3 text-[#cbf400]" />
</div>
<span className="text-sm text-gray-300">{item}</span>
</div>
))}
</div>
{/* CTA */}
<a
href="https://api.whatsapp.com/send?phone=551148101704&text=Olá!%20Gostaria%20de%20conhecer%20mais%20sobre%20a%20Avanzato"
target="_blank"
rel="noopener noreferrer"
className="animate-item btn-primary inline-flex items-center gap-2"
>
Conheça nossa história
</a>
</div>
</div>
{/* Stats */}
<div
ref={statsRef}
className="grid grid-cols-2 md:grid-cols-4 gap-6 mt-20 pt-12 border-t border-white/10"
>
<div className="text-center">
<Counter end={500} suffix="+" />
<div className="flex items-center justify-center gap-2 mt-2 text-gray-500">
<Users className="w-4 h-4" />
<span className="text-sm">Clientes atendidos</span>
</div>
</div>
<div className="text-center">
<Counter end={99} suffix=".9%" />
<div className="flex items-center justify-center gap-2 mt-2 text-gray-500">
<Clock className="w-4 h-4" />
<span className="text-sm">Uptime garantido</span>
</div>
</div>
<div className="text-center">
<Counter end={23} suffix="+" />
<div className="flex items-center justify-center gap-2 mt-2 text-gray-500">
<Award className="w-4 h-4" />
<span className="text-sm">Anos de experiência</span>
</div>
</div>
<div className="text-center">
<Counter end={24} suffix="/7" />
<div className="flex items-center justify-center gap-2 mt-2 text-gray-500">
<Users className="w-4 h-4" />
<span className="text-sm">Suporte técnico</span>
</div>
</div>
</div>
</div>
</section>
);
};
export default About;
+180
View File
@@ -0,0 +1,180 @@
import { useEffect, useRef } from 'react';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { Building2, Phone, Server, ArrowRight, CheckCircle2, Shield, Wifi } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Link } from 'react-router-dom';
gsap.registerPlugin(ScrollTrigger);
const CondominiosCTA = () => {
const sectionRef = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const ctx = gsap.context(() => {
const elements = contentRef.current?.querySelectorAll('.animate-item');
if (elements && elements.length > 0) {
gsap.fromTo(
elements,
{ y: 50, opacity: 0 },
{
y: 0,
opacity: 1,
duration: 0.7,
stagger: 0.1,
ease: 'expo.out',
scrollTrigger: {
trigger: sectionRef.current,
start: 'top 80%',
toggleActions: 'play none none reverse',
},
}
);
}
}, sectionRef);
return () => ctx.revert();
}, []);
const beneficios = [
'Redução de até 90% no investimento inicial',
'Independência de empresas de portaria',
'Ramais gratuitos para áreas comuns',
'Monitoramento 24/7',
];
return (
<section
ref={sectionRef}
className="section-padding bg-[#141414] relative overflow-hidden"
>
{/* Background decorations */}
<div className="absolute top-0 right-0 w-[500px] h-[500px] bg-[#cbf400]/5 rounded-full blur-[120px] -translate-y-1/2 translate-x-1/4" />
<div className="absolute bottom-0 left-0 w-[400px] h-[400px] bg-[#cbf400]/3 rounded-full blur-[100px] translate-y-1/2 -translate-x-1/4" />
<div className="container-custom relative z-10">
<div
ref={contentRef}
className="bg-gradient-to-br from-[#1a1a1a] to-[#0e0e0e] rounded-3xl p-8 md:p-12 lg:p-16 border border-[#cbf400]/20 relative overflow-hidden"
>
{/* Badge */}
<div className="animate-item inline-flex items-center gap-2 px-4 py-2 rounded-full bg-[#cbf400]/10 border border-[#cbf400]/20 mb-6">
<Building2 className="w-4 h-4 text-[#cbf400]" />
<span className="text-[#cbf400] text-sm font-medium">Nova Solução</span>
</div>
<div className="grid lg:grid-cols-2 gap-12 items-center">
{/* Content */}
<div>
<h2 className="animate-item text-3xl md:text-4xl lg:text-5xl font-black text-white mb-6 leading-tight">
Tecnologia para{' '}
<span className="text-gradient">Condomínios</span>
</h2>
<p className="animate-item text-gray-400 text-lg mb-8">
Infraestrutura própria, VOIP moderno e redução de custos.
Seu condomínio com tecnologia que não para.
</p>
{/* Benefícios */}
<div className="animate-item space-y-3 mb-8">
{beneficios.map((item, i) => (
<div key={i} className="flex items-center gap-3">
<CheckCircle2 className="w-5 h-5 text-[#cbf400] flex-shrink-0" />
<span className="text-gray-300">{item}</span>
</div>
))}
</div>
{/* CTA Buttons */}
<div className="animate-item flex flex-col sm:flex-row gap-4">
<Link to="/tecnologia-para-condominios">
<Button className="bg-[#cbf400] text-[#0e0e0e] hover:bg-[#b8e000] px-8 py-6 text-lg font-bold rounded-xl transition-all duration-300 hover:scale-105 w-full sm:w-auto">
Conhecer Solução
<ArrowRight className="ml-2 w-5 h-5" />
</Button>
</Link>
<Link to="/contato">
<Button
variant="outline"
className="border-white/20 text-white hover:bg-white/10 px-8 py-6 text-lg font-medium rounded-xl transition-all duration-300 w-full sm:w-auto"
>
Falar com Especialista
</Button>
</Link>
</div>
</div>
{/* Visual */}
<div className="animate-item relative">
<div className="absolute inset-0 bg-[#cbf400]/10 rounded-3xl blur-3xl" />
<div className="relative bg-[#0e0e0e] rounded-3xl p-8 border border-white/10">
{/* Cards de serviço */}
<div className="space-y-4">
<div className="flex items-center gap-4 p-4 bg-[#1a1a1a] rounded-xl border border-[#cbf400]/20">
<div className="w-12 h-12 rounded-xl bg-[#cbf400]/10 flex items-center justify-center">
<Phone className="w-6 h-6 text-[#cbf400]" />
</div>
<div>
<h4 className="text-white font-bold">VOIP para Condomínios</h4>
<p className="text-gray-500 text-sm">Comunicação moderna e econômica</p>
</div>
</div>
<div className="flex items-center gap-4 p-4 bg-[#1a1a1a] rounded-xl border border-white/10">
<div className="w-12 h-12 rounded-xl bg-blue-500/10 flex items-center justify-center">
<Server className="w-6 h-6 text-blue-400" />
</div>
<div>
<h4 className="text-white font-bold">Gestão de CPD</h4>
<p className="text-gray-500 text-sm">Infraestrutura profissional</p>
</div>
</div>
<div className="flex items-center gap-4 p-4 bg-[#1a1a1a] rounded-xl border border-white/10">
<div className="w-12 h-12 rounded-xl bg-purple-500/10 flex items-center justify-center">
<Wifi className="w-6 h-6 text-purple-400" />
</div>
<div>
<h4 className="text-white font-bold">Rede e Conectividade</h4>
<p className="text-gray-500 text-sm">Alta disponibilidade</p>
</div>
</div>
<div className="flex items-center gap-4 p-4 bg-[#1a1a1a] rounded-xl border border-white/10">
<div className="w-12 h-12 rounded-xl bg-red-500/10 flex items-center justify-center">
<Shield className="w-6 h-6 text-red-400" />
</div>
<div>
<h4 className="text-white font-bold">Segurança</h4>
<p className="text-gray-500 text-sm">Monitoramento 24/7</p>
</div>
</div>
</div>
{/* Stats */}
<div className="grid grid-cols-3 gap-4 mt-6 pt-6 border-t border-white/10">
<div className="text-center">
<div className="text-2xl font-black text-[#cbf400]">90%</div>
<div className="text-gray-500 text-xs">Economia</div>
</div>
<div className="text-center">
<div className="text-2xl font-black text-[#cbf400]">24/7</div>
<div className="text-gray-500 text-xs">Operação</div>
</div>
<div className="text-center">
<div className="text-2xl font-black text-[#cbf400]">500+</div>
<div className="text-gray-500 text-xs">Clientes</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
);
};
export default CondominiosCTA;
+408
View File
@@ -0,0 +1,408 @@
import { useEffect, useRef, useState } from 'react';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { Mail, Phone, MapPin, Send, Check, Loader2, Clock } from 'lucide-react';
gsap.registerPlugin(ScrollTrigger);
const Contact = () => {
const sectionRef = useRef<HTMLDivElement>(null);
const formRef = useRef<HTMLDivElement>(null);
const infoRef = useRef<HTMLDivElement>(null);
const canvasRef = useRef<HTMLCanvasElement>(null);
const [formData, setFormData] = useState({
name: '',
email: '',
company: '',
message: '',
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSubmitted, setIsSubmitted] = useState(false);
// Particle network animation
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d');
if (!ctx) return;
const resizeCanvas = () => {
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
};
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
const particles: Array<{
x: number;
y: number;
vx: number;
vy: number;
radius: number;
}> = [];
for (let i = 0; i < 30; i++) {
particles.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
vx: (Math.random() - 0.5) * 0.3,
vy: (Math.random() - 0.5) * 0.3,
radius: Math.random() * 2 + 1,
});
}
let mouseX = 0;
let mouseY = 0;
let isMouseInCanvas = false;
const handleMouseMove = (e: MouseEvent) => {
const rect = canvas.getBoundingClientRect();
mouseX = e.clientX - rect.left;
mouseY = e.clientY - rect.top;
isMouseInCanvas = true;
};
const handleMouseLeave = () => {
isMouseInCanvas = false;
};
canvas.addEventListener('mousemove', handleMouseMove);
canvas.addEventListener('mouseleave', handleMouseLeave);
let animationId: number;
const animate = () => {
ctx.fillStyle = 'rgba(26, 26, 26, 0.1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
particles.forEach((particle, i) => {
particle.x += particle.vx;
particle.y += particle.vy;
if (particle.x < 0 || particle.x > canvas.width) particle.vx *= -1;
if (particle.y < 0 || particle.y > canvas.height) particle.vy *= -1;
ctx.beginPath();
ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(203, 244, 0, 0.6)';
ctx.fill();
// Connect to mouse
if (isMouseInCanvas) {
const dx = particle.x - mouseX;
const dy = particle.y - mouseY;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 150) {
ctx.beginPath();
ctx.moveTo(particle.x, particle.y);
ctx.lineTo(mouseX, mouseY);
ctx.strokeStyle = `rgba(203, 244, 0, ${0.2 * (1 - distance / 150)})`;
ctx.stroke();
}
}
// Connect particles
particles.slice(i + 1).forEach((other) => {
const dx = particle.x - other.x;
const dy = particle.y - other.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
ctx.beginPath();
ctx.moveTo(particle.x, particle.y);
ctx.lineTo(other.x, other.y);
ctx.strokeStyle = `rgba(203, 244, 0, ${0.15 * (1 - distance / 100)})`;
ctx.stroke();
}
});
});
animationId = requestAnimationFrame(animate);
};
animate();
return () => {
window.removeEventListener('resize', resizeCanvas);
canvas.removeEventListener('mousemove', handleMouseMove);
canvas.removeEventListener('mouseleave', handleMouseLeave);
cancelAnimationFrame(animationId);
};
}, []);
// GSAP animations
useEffect(() => {
const ctx = gsap.context(() => {
gsap.fromTo(
formRef.current,
{ y: 50, opacity: 0 },
{
y: 0,
opacity: 1,
duration: 0.8,
ease: 'expo.out',
scrollTrigger: {
trigger: formRef.current,
start: 'top 80%',
toggleActions: 'play none none reverse',
},
}
);
gsap.fromTo(
infoRef.current,
{ x: 100, opacity: 0 },
{
x: 0,
opacity: 1,
duration: 0.8,
delay: 0.2,
ease: 'expo.out',
scrollTrigger: {
trigger: infoRef.current,
start: 'top 80%',
toggleActions: 'play none none reverse',
},
}
);
}, sectionRef);
return () => ctx.revert();
}, []);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsSubmitting(true);
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1500));
setIsSubmitting(false);
setIsSubmitted(true);
setFormData({ name: '', email: '', company: '', message: '' });
// Reset success message after 5 seconds
setTimeout(() => setIsSubmitted(false), 5000);
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
setFormData(prev => ({
...prev,
[e.target.name]: e.target.value,
}));
};
const contactInfo = [
{
icon: <Mail className="w-5 h-5" />,
label: 'Email',
value: 'contato@avanzato.com.br',
href: 'mailto:contato@avanzato.com.br',
},
{
icon: <Phone className="w-5 h-5" />,
label: 'Telefone',
value: '(11) 4810-1704',
href: 'tel:+551148101704',
},
{
icon: <MapPin className="w-5 h-5" />,
label: 'Endereço',
value: 'Av. Dr. Carlos de Campos, 43 - Guarulhos/SP',
href: 'https://maps.google.com/?q=Av.+Dr.+Carlos+de+Campos,+43+Guarulhos+SP',
},
];
return (
<section
id="contact"
ref={sectionRef}
className="section-padding bg-[#0e0e0e] relative overflow-hidden"
>
<div className="container-custom">
<div className="grid lg:grid-cols-2 gap-0 rounded-2xl overflow-hidden shadow-2xl border border-white/5">
{/* Form section */}
<div ref={formRef} className="bg-[#1a1a1a] p-8 md:p-12">
<span className="inline-block px-4 py-2 rounded-full bg-[#cbf400]/10 text-[#cbf400] text-sm font-semibold mb-4 border border-[#cbf400]/20">
Contato
</span>
<h2 className="text-3xl md:text-4xl font-black text-white mb-4">
Vamos <span className="text-gradient">conversar</span>
</h2>
<p className="text-gray-400 mb-8">
Preencha o formulário abaixo e nossa equipe entrará em contato em até 24 horas.
</p>
{isSubmitted ? (
<div className="flex flex-col items-center justify-center py-12 text-center">
<div className="w-16 h-16 rounded-full bg-[#cbf400]/20 flex items-center justify-center mb-4 border border-[#cbf400]/30">
<Check className="w-8 h-8 text-[#cbf400]" />
</div>
<h3 className="text-xl font-bold text-white mb-2">Mensagem enviada!</h3>
<p className="text-gray-400">Entraremos em contato em breve.</p>
</div>
) : (
<form onSubmit={handleSubmit} className="space-y-6">
<div className="grid sm:grid-cols-2 gap-6">
<div className="input-focus">
<label className="block text-sm font-semibold text-gray-300 mb-2">
Nome
</label>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
required
className="w-full px-4 py-3 rounded-lg bg-[#0e0e0e] border border-white/10 text-white focus:border-[#cbf400] focus:ring-2 focus:ring-[#cbf400]/20 outline-none transition-all"
placeholder="Seu nome"
/>
</div>
<div className="input-focus">
<label className="block text-sm font-semibold text-gray-300 mb-2">
Email
</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
required
className="w-full px-4 py-3 rounded-lg bg-[#0e0e0e] border border-white/10 text-white focus:border-[#cbf400] focus:ring-2 focus:ring-[#cbf400]/20 outline-none transition-all"
placeholder="seu@email.com"
/>
</div>
</div>
<div className="input-focus">
<label className="block text-sm font-semibold text-gray-300 mb-2">
Empresa
</label>
<input
type="text"
name="company"
value={formData.company}
onChange={handleChange}
className="w-full px-4 py-3 rounded-lg bg-[#0e0e0e] border border-white/10 text-white focus:border-[#cbf400] focus:ring-2 focus:ring-[#cbf400]/20 outline-none transition-all"
placeholder="Nome da sua empresa"
/>
</div>
<div className="input-focus">
<label className="block text-sm font-semibold text-gray-300 mb-2">
Mensagem
</label>
<textarea
name="message"
value={formData.message}
onChange={handleChange}
required
rows={4}
className="w-full px-4 py-3 rounded-lg bg-[#0e0e0e] border border-white/10 text-white focus:border-[#cbf400] focus:ring-2 focus:ring-[#cbf400]/20 outline-none transition-all resize-none"
placeholder="Como podemos ajudar?"
/>
</div>
<button
type="submit"
disabled={isSubmitting}
className="btn-primary w-full flex items-center justify-center gap-2 disabled:opacity-70"
>
{isSubmitting ? (
<>
<Loader2 className="w-5 h-5 animate-spin" />
Enviando...
</>
) : (
<>
Enviar mensagem
<Send className="w-5 h-5" />
</>
)}
</button>
</form>
)}
</div>
{/* Info section */}
<div ref={infoRef} className="relative bg-[#0e0e0e] p-8 md:p-12 overflow-hidden">
{/* Particle canvas */}
<canvas
ref={canvasRef}
className="absolute inset-0 w-full h-full"
/>
{/* Content */}
<div className="relative z-10">
<h3 className="text-2xl font-bold text-white mb-6">
Informações de contato
</h3>
<div className="space-y-6 mb-12">
{contactInfo.map((item, index) => (
<a
key={index}
href={item.href}
target={item.href.startsWith('http') ? '_blank' : undefined}
rel={item.href.startsWith('http') ? 'noopener noreferrer' : undefined}
className="flex items-start gap-4 group"
>
<div className="w-10 h-10 rounded-lg bg-[#cbf400]/10 flex items-center justify-center text-[#cbf400] group-hover:bg-[#cbf400] group-hover:text-[#0e0e0e] transition-colors border border-[#cbf400]/20">
{item.icon}
</div>
<div>
<div className="text-sm text-gray-500">{item.label}</div>
<div className="text-white group-hover:text-[#cbf400] transition-colors font-medium">
{item.value}
</div>
</div>
</a>
))}
</div>
{/* WhatsApp CTA */}
<div className="bg-[#1a1a1a] backdrop-blur-sm rounded-xl p-6 border border-white/5">
<h4 className="text-white font-semibold mb-2">
Prefere falar pelo WhatsApp?
</h4>
<p className="text-gray-400 text-sm mb-4">
Nossa equipe está disponível para atendimento imediato.
</p>
<a
href="https://api.whatsapp.com/send?phone=551148101704&text=Olá!%20Gostaria%20de%20saber%20mais%20sobre%20os%20serviços%20da%20Avanzato"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 text-[#cbf400] hover:text-[#d4ff1a] transition-colors font-medium"
>
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
</svg>
Iniciar conversa
</a>
</div>
{/* Hours */}
<div className="mt-8 pt-8 border-t border-white/10">
<div className="flex items-center gap-2 text-gray-500 text-sm mb-2">
<Clock className="w-4 h-4" />
<span>Horário de atendimento</span>
</div>
<div className="text-white font-medium">
Segunda a Sexta: 8h às 18h
</div>
<div className="text-[#cbf400] text-sm mt-1 font-medium">
Suporte técnico: 24/7
</div>
</div>
</div>
</div>
</div>
</div>
</section>
);
};
export default Contact;
+192
View File
@@ -0,0 +1,192 @@
import { Link } from 'react-router-dom';
import { Facebook, Youtube, Linkedin, Instagram, ArrowUp, MapPin } from 'lucide-react';
import { LOGO, SOCIAL_LINKS, ADDRESSES, FOOTER_LINKS, COMPANY } from '../config/site';
// Mapa de icones das redes sociais
const socialIcons: Record<string, React.ReactNode> = {
facebook: <Facebook className="w-5 h-5" />,
youtube: <Youtube className="w-5 h-5" />,
linkedin: <Linkedin className="w-5 h-5" />,
instagram: <Instagram className="w-5 h-5" />,
};
const Footer = () => {
const scrollToTop = () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
};
// Filtra apenas redes sociais com URL preenchida
const activeSocials = Object.entries(SOCIAL_LINKS)
.filter(([, data]) => data.url)
.map(([key, data]) => ({
key,
icon: data.iconSvg
? <div dangerouslySetInnerHTML={{ __html: data.iconSvg }} />
: (socialIcons[key] || null),
href: data.url,
label: data.label,
}));
// Renderiza o logo (SVG inline ou imagem)
const renderLogo = () => {
if (LOGO.imageUrl) {
return <img src={LOGO.imageUrl} alt={COMPANY.name} className="h-10 w-auto" />;
}
return (
<div dangerouslySetInnerHTML={{ __html: LOGO.svgInline }} className="flex-shrink-0" />
);
};
return (
<footer className="bg-[#0e0e0e] text-white relative border-t border-white/5">
{/* Main footer */}
<div className="container-custom py-16">
<div className="grid md:grid-cols-2 lg:grid-cols-5 gap-12">
{/* Brand */}
<div className="lg:col-span-2">
<Link to={LOGO.href} className="flex items-center gap-3 mb-6">
{renderLogo()}
{LOGO.text && (
<span className="text-2xl font-bold tracking-tight">
{LOGO.text}
<span className="text-[#cbf400]">{LOGO.textHighlight}</span>
</span>
)}
</Link>
<p className="text-gray-400 mb-6 max-w-sm">
{COMPANY.description}
</p>
{/* Enderecos - importados de config/site.ts */}
{ADDRESSES.length > 0 && (
<div className="mb-6">
<div className="flex items-center gap-2 mb-3">
<MapPin className="w-4 h-4 text-[#cbf400]" />
<span className="text-white font-medium text-sm">Nossos Escritorios</span>
</div>
<div className="space-y-2 text-xs text-gray-400">
{ADDRESSES.map((addr, i) => (
<p key={i}>{addr.street} - {addr.city}/{addr.state}</p>
))}
</div>
</div>
)}
{/* Social links - importados de config/site.ts */}
{activeSocials.length > 0 && (
<div className="flex gap-3">
{activeSocials.map((social) => (
<a
key={social.key}
href={social.href}
target="_blank"
rel="noopener noreferrer"
aria-label={social.label}
className="w-10 h-10 rounded-lg bg-white/5 flex items-center justify-center text-gray-400 hover:bg-[#cbf400] hover:text-[#0e0e0e] transition-colors border border-white/5"
>
{social.icon}
</a>
))}
</div>
)}
</div>
{/* Services */}
<div>
<h4 className="font-bold mb-4 text-white">Servicos</h4>
<ul className="space-y-3">
{FOOTER_LINKS.servicos.map((link, index) => (
<li key={index}>
<Link
to={link.href}
className="text-gray-400 hover:text-[#cbf400] transition-colors text-sm"
>
{link.name}
</Link>
</li>
))}
</ul>
</div>
{/* Company */}
<div>
<h4 className="font-bold mb-4 text-white">Empresa</h4>
<ul className="space-y-3">
{FOOTER_LINKS.empresa.map((link, index) => (
<li key={index}>
<Link
to={link.href}
className="text-gray-400 hover:text-[#cbf400] transition-colors text-sm"
>
{link.name}
</Link>
</li>
))}
</ul>
</div>
{/* Support */}
<div>
<h4 className="font-bold mb-4 text-white">Suporte</h4>
<ul className="space-y-3">
{FOOTER_LINKS.suporte.map((link, index) => (
<li key={index}>
{link.href.startsWith('http') ? (
<a
href={link.href}
target="_blank"
rel="noopener noreferrer"
className="text-gray-400 hover:text-[#cbf400] transition-colors text-sm"
>
{link.name}
</a>
) : (
<Link
to={link.href}
className="text-gray-400 hover:text-[#cbf400] transition-colors text-sm"
>
{link.name}
</Link>
)}
</li>
))}
</ul>
</div>
</div>
</div>
{/* Bottom bar */}
<div className="border-t border-white/5">
<div className="container-custom py-6">
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
<p className="text-gray-500 text-sm">
&copy; {new Date().getFullYear()} {COMPANY.name}. Todos os direitos reservados.
</p>
<div className="flex items-center gap-6">
{FOOTER_LINKS.legais.map((link, index) => (
<Link
key={index}
to={link.href}
className="text-gray-500 hover:text-gray-300 text-sm transition-colors"
>
{link.name}
</Link>
))}
</div>
<button
onClick={scrollToTop}
className="w-10 h-10 rounded-full bg-[#cbf400]/10 flex items-center justify-center text-[#cbf400] hover:bg-[#cbf400] hover:text-[#0e0e0e] transition-all"
aria-label="Voltar ao topo"
>
<ArrowUp className="w-5 h-5" />
</button>
</div>
</div>
</div>
</footer>
);
};
export default Footer;
+292
View File
@@ -0,0 +1,292 @@
import { useEffect, useRef, useState } from 'react';
import { gsap } from 'gsap';
import { ArrowRight, Play } from 'lucide-react';
import GlowButton from '../components/GlowButton';
const Hero = () => {
const heroRef = useRef<HTMLDivElement>(null);
const titleRef = useRef<HTMLHeadingElement>(null);
const subtitleRef = useRef<HTMLParagraphElement>(null);
const ctaRef = useRef<HTMLDivElement>(null);
const imageRef = useRef<HTMLDivElement>(null);
const canvasRef = useRef<HTMLCanvasElement>(null);
const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
// Animated background
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d');
if (!ctx) return;
const resizeCanvas = () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
// Particles
const particles: Array<{
x: number;
y: number;
vx: number;
vy: number;
radius: number;
opacity: number;
}> = [];
for (let i = 0; i < 50; i++) {
particles.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
vx: (Math.random() - 0.5) * 0.5,
vy: (Math.random() - 0.5) * 0.5,
radius: Math.random() * 2 + 1,
opacity: Math.random() * 0.5 + 0.2,
});
}
let animationId: number;
const animate = () => {
ctx.fillStyle = 'rgba(14, 14, 14, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
particles.forEach((particle, i) => {
particle.x += particle.vx;
particle.y += particle.vy;
if (particle.x < 0 || particle.x > canvas.width) particle.vx *= -1;
if (particle.y < 0 || particle.y > canvas.height) particle.vy *= -1;
ctx.beginPath();
ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2);
ctx.fillStyle = `rgba(203, 244, 0, ${particle.opacity})`;
ctx.fill();
// Connect particles
particles.slice(i + 1).forEach((other) => {
const dx = particle.x - other.x;
const dy = particle.y - other.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 150) {
ctx.beginPath();
ctx.moveTo(particle.x, particle.y);
ctx.lineTo(other.x, other.y);
ctx.strokeStyle = `rgba(203, 244, 0, ${0.1 * (1 - distance / 150)})`;
ctx.stroke();
}
});
});
animationId = requestAnimationFrame(animate);
};
animate();
return () => {
window.removeEventListener('resize', resizeCanvas);
cancelAnimationFrame(animationId);
};
}, []);
// GSAP animations
useEffect(() => {
const ctx = gsap.context(() => {
// Title animation
gsap.fromTo(
titleRef.current,
{ y: 100, opacity: 0 },
{ y: 0, opacity: 1, duration: 0.8, delay: 0.2, ease: 'expo.out' }
);
// Subtitle animation
gsap.fromTo(
subtitleRef.current,
{ y: 50, opacity: 0 },
{ y: 0, opacity: 1, duration: 0.6, delay: 0.4, ease: 'expo.out' }
);
// CTA animation
gsap.fromTo(
ctaRef.current,
{ scale: 0.8, opacity: 0 },
{ scale: 1, opacity: 1, duration: 0.6, delay: 0.6, ease: 'back.out(1.7)' }
);
// Image animation
gsap.fromTo(
imageRef.current,
{ rotateX: 45, opacity: 0, y: 50 },
{ rotateX: 0, opacity: 1, y: 0, duration: 1.2, delay: 0.4, ease: 'elastic.out(1, 0.5)' }
);
}, heroRef);
return () => ctx.revert();
}, []);
// Mouse parallax effect
useEffect(() => {
const handleMouseMove = (e: MouseEvent) => {
const x = (e.clientX / window.innerWidth - 0.5) * 20;
const y = (e.clientY / window.innerHeight - 0.5) * 20;
setMousePos({ x, y });
};
window.addEventListener('mousemove', handleMouseMove, { passive: true });
return () => window.removeEventListener('mousemove', handleMouseMove);
}, []);
return (
<section
id="hero"
ref={heroRef}
className="relative min-h-screen flex items-center overflow-hidden bg-[#0e0e0e]"
>
{/* Animated background canvas */}
<canvas
ref={canvasRef}
className="absolute inset-0 w-full h-full"
style={{ opacity: 0.8 }}
/>
{/* Gradient overlay */}
<div className="absolute inset-0 bg-gradient-to-br from-[#cbf400]/5 via-transparent to-transparent" />
{/* Content */}
<div className="container-custom relative z-10 pt-32 pb-20">
<div className="grid lg:grid-cols-2 gap-12 items-center">
{/* Left content */}
<div className="text-white">
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-[#cbf400]/10 backdrop-blur-sm mb-6 border border-[#cbf400]/20">
<span className="w-2 h-2 rounded-full bg-[#cbf400] animate-pulse" />
<span className="text-sm font-semibold text-[#cbf400]">+23 anos de experiência</span>
</div>
<h1
ref={titleRef}
className="text-4xl md:text-5xl lg:text-6xl font-black leading-tight mb-6"
style={{ fontFamily: 'Urbanist, sans-serif' }}
>
Tecnologia que{' '}
<span className="text-gradient">impulsiona</span> seu negócio
</h1>
<p
ref={subtitleRef}
className="text-lg md:text-xl text-gray-400 mb-8 max-w-xl font-medium"
>
Soluções em TI Gerenciada, Cloud e Segurança para empresas que não podem parar.
Seu parceiro estratégico em transformação digital.
</p>
<div ref={ctaRef} className="flex flex-wrap gap-4">
<a
href="https://api.whatsapp.com/send?phone=551148101704&text=Olá!%20Visitei%20o%20site%20e%20gostaria%20de%20saber%20mais%20informações%20sobre%20os%20serviços"
target="_blank"
rel="noopener noreferrer"
className="btn-primary inline-flex items-center gap-2"
>
Fale com um especialista
<ArrowRight className="w-5 h-5" />
</a>
<a
href="#services"
onClick={(e) => {
e.preventDefault();
document.querySelector('#services')?.scrollIntoView({ behavior: 'smooth' });
}}
className="btn-secondary inline-flex items-center gap-2"
>
<Play className="w-5 h-5" />
Conheça nossos serviços
</a>
</div>
{/* Botao Avaliacao TI - Super destacado */}
<div className="mt-6">
<GlowButton
to="/avaliacao"
text="Avalie a maturidade da sua TI"
size="lg"
/>
<p className="text-gray-500 text-sm mt-2 ml-1">
Descubra o nivel de maturidade tecnologica da sua empresa em 2 minutos
</p>
</div>
{/* Stats */}
<div className="grid grid-cols-3 gap-6 mt-12 pt-8 border-t border-white/10">
<div>
<div className="text-3xl md:text-4xl font-black text-[#cbf400]">+500</div>
<div className="text-sm text-gray-500 font-medium">Clientes atendidos</div>
</div>
<div>
<div className="text-3xl md:text-4xl font-black text-[#cbf400]">99.9%</div>
<div className="text-sm text-gray-500 font-medium">Uptime garantido</div>
</div>
<div>
<div className="text-3xl md:text-4xl font-black text-[#cbf400]">24/7</div>
<div className="text-sm text-gray-500 font-medium">Suporte técnico</div>
</div>
</div>
</div>
{/* Right content - Dashboard Image */}
<div
ref={imageRef}
className="relative lg:pl-8"
style={{
transform: `perspective(1000px) rotateY(${mousePos.x * 0.5}deg) rotateX(${-mousePos.y * 0.5}deg)`,
transition: 'transform 0.1s ease-out',
}}
>
<div className="relative animate-float">
{/* Glow effect */}
<div className="absolute -inset-4 bg-gradient-to-r from-[#cbf400]/20 to-[#cbf400]/10 rounded-2xl blur-2xl opacity-50" />
{/* Dashboard image */}
<div className="relative rounded-2xl overflow-hidden shadow-2xl border border-[#cbf400]/20">
<img
src="/hero-dashboard.jpg"
alt="Dashboard Avanzato"
className="w-full h-auto"
/>
{/* Glossy overlay */}
<div
className="absolute inset-0 bg-gradient-to-br from-white/10 via-transparent to-transparent pointer-events-none"
style={{
transform: `translateX(${mousePos.x}%) translateY(${mousePos.y}%)`,
}}
/>
</div>
{/* Floating badge */}
<div className="absolute -bottom-4 -left-4 bg-[#1a1a1a] rounded-xl p-4 shadow-xl border border-[#cbf400]/30">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-full bg-[#cbf400]/20 flex items-center justify-center">
<svg className="w-5 h-5 text-[#cbf400]" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<div className="text-white font-bold text-sm">Sistema operacional</div>
<div className="text-gray-500 text-xs">Todos os serviços ativos</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Bottom gradient fade */}
<div className="absolute bottom-0 left-0 right-0 h-32 bg-gradient-to-t from-[#0e0e0e] to-transparent" />
</section>
);
};
export default Hero;
+184
View File
@@ -0,0 +1,184 @@
import { useState, useEffect } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { Menu, X, Phone, ChevronDown } from 'lucide-react';
import { LOGO, NAV_LINKS, CONTACT } from '../config/site';
const Navigation = () => {
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [isServicesOpen, setIsServicesOpen] = useState(false);
const location = useLocation();
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
};
window.addEventListener('scroll', handleScroll, { passive: true });
return () => window.removeEventListener('scroll', handleScroll);
}, []);
// Fechar menu mobile ao mudar de rota
useEffect(() => {
setIsMobileMenuOpen(false);
setIsServicesOpen(false);
}, [location]);
const isActive = (path: string) => {
if (path === '/') {
return location.pathname === '/';
}
return location.pathname.startsWith(path);
};
// Renderiza o logo (SVG inline ou imagem)
const renderLogo = () => {
if (LOGO.imageUrl) {
return <img src={LOGO.imageUrl} alt={LOGO.text} className="h-10 w-auto" />;
}
return (
<div dangerouslySetInnerHTML={{ __html: LOGO.svgInline }} className="flex-shrink-0" />
);
};
return (
<nav className={`nav-sticky ${isScrolled ? 'scrolled' : ''}`}>
<div className="container-custom">
<div className="flex items-center justify-between h-20">
{/* Logo - importado de config/site.ts */}
<Link to={LOGO.href} className="flex items-center gap-3">
{renderLogo()}
{LOGO.text && (
<span className="text-2xl font-bold text-white tracking-tight">
{LOGO.text}
<span className="text-[#cbf400]">{LOGO.textHighlight}</span>
</span>
)}
</Link>
{/* Desktop Navigation - importado de config/site.ts */}
<div className="hidden lg:flex items-center gap-8">
{NAV_LINKS.map((link) => (
<div key={link.name} className="relative">
{link.submenu ? (
<div
className="relative"
onMouseEnter={() => setIsServicesOpen(true)}
onMouseLeave={() => setIsServicesOpen(false)}
>
<button
className={`flex items-center gap-1 nav-link text-sm font-medium transition-colors ${
link.submenu.some(s => location.pathname.startsWith(s.href))
? 'text-[#cbf400]'
: 'text-gray-300 hover:text-white'
}`}
>
{link.name}
<ChevronDown className={`w-4 h-4 transition-transform ${isServicesOpen ? 'rotate-180' : ''}`} />
</button>
{isServicesOpen && (
<div className="absolute top-full left-0 mt-2 w-56 bg-[#1a1a1a] rounded-xl border border-white/10 shadow-xl py-2 z-50">
{link.submenu.map((sub) => (
<Link
key={sub.name}
to={sub.href}
className="block px-4 py-2.5 text-sm text-gray-300 hover:text-[#cbf400] hover:bg-white/5 transition-colors"
>
{sub.name}
</Link>
))}
</div>
)}
</div>
) : (
<Link
to={link.href}
className={`nav-link text-sm font-medium transition-colors ${
isActive(link.href) ? 'text-[#cbf400]' : 'text-gray-300 hover:text-white'
}`}
>
{link.name}
</Link>
)}
</div>
))}
</div>
{/* Desktop CTA - importado de config/site.ts */}
<div className="hidden lg:flex items-center gap-4">
<a
href={`tel:${CONTACT.phoneRaw}`}
className="flex items-center gap-2 text-sm text-gray-400 hover:text-[#cbf400] transition-colors"
>
<Phone className="w-4 h-4" />
{CONTACT.phone}
</a>
</div>
{/* Mobile Menu Button */}
<button
className="lg:hidden p-2 text-gray-300 hover:text-white"
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
aria-label="Menu"
>
{isMobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
</button>
</div>
{/* Mobile Menu - importado de config/site.ts */}
{isMobileMenuOpen && (
<div className="lg:hidden py-4 border-t border-white/10">
<div className="flex flex-col gap-4">
{NAV_LINKS.map((link) => (
<div key={link.name}>
{link.submenu ? (
<div>
<button
onClick={() => setIsServicesOpen(!isServicesOpen)}
className="flex items-center justify-between w-full text-gray-300 hover:text-[#cbf400] transition-colors py-2"
>
<span className="font-medium">{link.name}</span>
<ChevronDown className={`w-4 h-4 transition-transform ${isServicesOpen ? 'rotate-180' : ''}`} />
</button>
{isServicesOpen && (
<div className="pl-4 mt-2 space-y-2">
{link.submenu.map((sub) => (
<Link
key={sub.name}
to={sub.href}
className="block text-sm text-gray-400 hover:text-[#cbf400] py-1"
>
{sub.name}
</Link>
))}
</div>
)}
</div>
) : (
<Link
to={link.href}
className={`block py-2 font-medium transition-colors ${
isActive(link.href) ? 'text-[#cbf400]' : 'text-gray-300 hover:text-[#cbf400]'
}`}
>
{link.name}
</Link>
)}
</div>
))}
<a
href={`tel:${CONTACT.phoneRaw}`}
className="flex items-center gap-2 text-sm text-gray-400 hover:text-[#cbf400] pt-4 border-t border-white/10"
>
<Phone className="w-4 h-4" />
{CONTACT.phone}
</a>
</div>
</div>
)}
</div>
</nav>
);
};
export default Navigation;
+298
View File
@@ -0,0 +1,298 @@
import { useEffect, useRef, useState } from 'react';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { ArrowRight, Server, Cloud, Shield, Headphones, Network, Phone, HardDrive, Cpu, ClipboardCheck, Monitor } from 'lucide-react';
gsap.registerPlugin(ScrollTrigger);
interface Service {
id: number;
title: string;
description: string;
image: string;
icon: React.ReactNode;
features: string[];
link: string;
}
const services: Service[] = [
{
id: 1,
title: 'TI Gerenciada',
description: 'Monitoramento 24/7 de toda sua infraestrutura. Foco no seu negócio enquanto cuidamos da sua tecnologia.',
image: '/service-ti.png',
icon: <Server className="w-6 h-6" />,
features: ['Monitoramento proativo', 'Gestão de infraestrutura', 'Backup automatizado', 'Relatórios mensais'],
link: '/servicos/ti-gerenciada',
},
{
id: 2,
title: 'Cloud Computing',
description: 'Migração e gestão de ambientes em nuvem. Escalabilidade e segurança para seu crescimento.',
image: '/service-cloud.png',
icon: <Cloud className="w-6 h-6" />,
features: ['Migração para nuvem', 'AWS/Azure/GCP', 'Otimização de custos', 'Arquitetura serverless'],
link: '/servicos/cloud-computing',
},
{
id: 3,
title: 'Segurança',
description: 'Proteção contra ameaças digitais. Segurança de ponta a ponta para seus dados e sistemas.',
image: '/service-security.png',
icon: <Shield className="w-6 h-6" />,
features: ['Firewall gerenciado', 'Antivírus corporativo', 'VPN segura', 'Auditoria de segurança'],
link: '/servicos/seguranca',
},
{
id: 4,
title: 'Suporte Técnico',
description: 'Atendimento ágil para seus colaboradores. Resolução rápida de problemas técnicos.',
image: '/service-support.png',
icon: <Headphones className="w-6 h-6" />,
features: ['Help desk 24/7', 'Suporte remoto', 'Atendimento presencial', 'Base de conhecimento'],
link: '/servicos/suporte',
},
{
id: 5,
title: 'Infraestrutura de Redes',
description: 'Redes corporativas seguras, rápidas e escaláveis. Cabeamento e configuração profissional.',
image: '/service-ti.png',
icon: <Network className="w-6 h-6" />,
features: ['Cabeamento estruturado', 'Wi-Fi corporativo', 'VLANs', 'Switches gerenciáveis'],
link: '/servicos/redes',
},
{
id: 6,
title: 'PABX em Nuvem',
description: 'Telefonia IP moderna e econômica. Reduza custos e modernize sua comunicação.',
image: '/service-support.png',
icon: <Phone className="w-6 h-6" />,
features: ['Ramais remotos', 'URA', 'Gravação de chamadas', 'Integração CRM'],
link: '/servicos/pabx',
},
{
id: 7,
title: 'Backup Corporativo',
description: 'Proteção total contra perda de dados. Backup em nuvem e recuperação de desastres.',
image: '/service-cloud.png',
icon: <HardDrive className="w-6 h-6" />,
features: ['Backup automático', 'Proteção ransomware', 'Recuperação rápida', 'DRaaS'],
link: '/servicos/backup',
},
{
id: 8,
title: 'Servidores',
description: 'Implantação e virtualização de servidores. Alta performance e disponibilidade.',
image: '/service-ti.png',
icon: <Cpu className="w-6 h-6" />,
features: ['Virtualização', 'Servidor de arquivos', 'Alta disponibilidade', 'Redução de custos'],
link: '/servicos/servidores',
},
{
id: 9,
title: 'Consultoria em TI',
description: 'Planejamento estratégico tecnológico. Diagnóstico e roadmap para sua empresa.',
image: '/about-image.jpg',
icon: <ClipboardCheck className="w-6 h-6" />,
features: ['Diagnóstico', 'Planejamento', 'Auditoria', 'Roadmap estratégico'],
link: '/servicos/consultoria',
},
{
id: 10,
title: 'Monitoramento e NOC',
description: 'Visibilidade total da sua infraestrutura. Monitoramento 24/7 com alertas em tempo real.',
image: '/service-ti.png',
icon: <Monitor className="w-6 h-6" />,
features: ['Monitoramento 24/7', 'Alertas em tempo real', 'Painéis personalizados', 'Prevenção de falhas'],
link: '/servicos/noc',
},
];
const ServiceCard = ({ service }: { service: Service }) => {
const cardRef = useRef<HTMLDivElement>(null);
const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
const [isHovered, setIsHovered] = useState(false);
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
if (!cardRef.current) return;
const rect = cardRef.current.getBoundingClientRect();
const x = (e.clientX - rect.left - rect.width / 2) / 20;
const y = (e.clientY - rect.top - rect.height / 2) / 20;
setMousePos({ x, y });
};
return (
<div
ref={cardRef}
className="service-card-border group relative bg-[#1a1a1a] rounded-2xl overflow-hidden shadow-lg cursor-pointer border border-white/5"
style={{
transform: isHovered
? `perspective(1000px) rotateX(${-mousePos.y}deg) rotateY(${mousePos.x}deg) translateZ(20px)`
: 'perspective(1000px) rotateX(0) rotateY(0) translateZ(0)',
transition: 'transform 0.3s ease-out',
}}
onMouseMove={handleMouseMove}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => {
setIsHovered(false);
setMousePos({ x: 0, y: 0 });
}}
>
{/* Image container */}
<div className="relative h-48 bg-gradient-to-br from-[#2a2a2a] to-[#1a1a1a] overflow-hidden">
<img
src={service.image}
alt={service.title}
className="w-full h-full object-contain p-6 transition-transform duration-500 group-hover:scale-110"
/>
{/* Icon badge */}
<div className="absolute top-4 left-4 w-12 h-12 rounded-xl bg-[#0e0e0e] shadow-lg flex items-center justify-center text-[#cbf400] border border-[#cbf400]/20">
{service.icon}
</div>
{/* Gradient overlay on hover */}
<div className="absolute inset-0 bg-gradient-to-t from-[#cbf400]/10 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
</div>
{/* Content */}
<div className="p-5">
<h3 className="text-lg font-bold text-white mb-2 group-hover:text-[#cbf400] transition-colors">
{service.title}
</h3>
<p className="text-gray-400 text-sm mb-4 line-clamp-2">
{service.description}
</p>
{/* Features list */}
<ul className="space-y-1.5 mb-4">
{service.features.slice(0, 3).map((feature, i) => (
<li key={i} className="flex items-center gap-2 text-xs text-gray-300">
<span className="w-1.5 h-1.5 rounded-full bg-[#cbf400]" />
{feature}
</li>
))}
</ul>
{/* CTA */}
<a
href={service.link}
className="inline-flex items-center gap-2 text-[#cbf400] font-semibold text-sm group/link"
>
Saiba mais
<ArrowRight className="w-4 h-4 transition-transform group-hover/link:translate-x-1" />
</a>
</div>
{/* Glow border effect */}
<div className="absolute inset-0 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-300 pointer-events-none">
<div className="absolute inset-0 rounded-2xl bg-gradient-to-r from-[#cbf400]/20 via-[#cbf400]/10 to-[#cbf400]/20 blur-sm" />
</div>
</div>
);
};
const Services = () => {
const sectionRef = useRef<HTMLDivElement>(null);
const titleRef = useRef<HTMLDivElement>(null);
const cardsRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const ctx = gsap.context(() => {
gsap.fromTo(
titleRef.current,
{ y: 50, opacity: 0 },
{
y: 0,
opacity: 1,
duration: 0.8,
ease: 'expo.out',
scrollTrigger: {
trigger: titleRef.current,
start: 'top 80%',
toggleActions: 'play none none reverse',
},
}
);
const cards = cardsRef.current?.querySelectorAll('.service-card-border');
if (cards) {
gsap.fromTo(
cards,
{ y: 100, opacity: 0 },
{
y: 0,
opacity: 1,
duration: 0.8,
stagger: 0.08,
ease: 'expo.out',
scrollTrigger: {
trigger: cardsRef.current,
start: 'top 80%',
toggleActions: 'play none none reverse',
},
}
);
}
}, sectionRef);
return () => ctx.revert();
}, []);
return (
<section
id="services"
ref={sectionRef}
className="section-padding bg-[#0e0e0e] relative overflow-hidden"
>
{/* Background decoration */}
<div className="absolute top-0 right-0 w-96 h-96 bg-[#cbf400]/5 rounded-full blur-3xl -translate-y-1/2 translate-x-1/2" />
<div className="absolute bottom-0 left-0 w-96 h-96 bg-[#cbf400]/5 rounded-full blur-3xl translate-y-1/2 -translate-x-1/2" />
<div className="container-custom relative z-10">
{/* Section header */}
<div ref={titleRef} className="text-center max-w-2xl mx-auto mb-16">
<span className="inline-block px-4 py-2 rounded-full bg-[#cbf400]/10 text-[#cbf400] text-sm font-semibold mb-4 border border-[#cbf400]/20">
Nossas Soluções
</span>
<h2 className="text-3xl md:text-4xl lg:text-5xl font-black text-white mb-4">
Serviços completos em{' '}
<span className="text-gradient">Tecnologia</span>
</h2>
<p className="text-gray-400 text-lg">
Oferecemos soluções integradas para transformar a infraestrutura de TI da sua empresa
em um diferencial competitivo.
</p>
</div>
{/* Services grid */}
<div
ref={cardsRef}
className="grid md:grid-cols-2 lg:grid-cols-5 gap-5"
>
{services.map((service) => (
<ServiceCard key={service.id} service={service} />
))}
</div>
{/* Bottom CTA */}
<div className="text-center mt-12">
<p className="text-gray-400 mb-4">
Precisa de uma solução personalizada?
</p>
<a
href="https://api.whatsapp.com/send?phone=551148101704&text=Olá!%20Gostaria%20de%20uma%20solução%20personalizada"
target="_blank"
rel="noopener noreferrer"
className="btn-primary inline-flex items-center gap-2"
>
Fale com um consultor
<ArrowRight className="w-5 h-5" />
</a>
</div>
</div>
</section>
);
};
export default Services;
+371
View File
@@ -0,0 +1,371 @@
import { useEffect, useRef } from 'react';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { Star, Building2, MapPin } from 'lucide-react';
gsap.registerPlugin(ScrollTrigger);
interface Testimonial {
id: number;
cliente: string;
responsavel: string;
cargo?: string;
segmento: string;
cidade: string;
quote: string;
destaque: string;
icone: string;
}
const testimonials: Testimonial[] = [
{
id: 1,
cliente: "Moraes & Moraes Advogados",
responsavel: "Edilson Fernando de Moraes",
segmento: "Advocacia",
cidade: "São Paulo",
quote: "Evitamos um investimento de mais de R$ 15.000 com a solução aplicada.",
destaque: "Economia de R$ 15.000",
icone: "⚖️"
},
{
id: 2,
cliente: "Divas Car",
responsavel: "Joelma Rodrigues",
segmento: "Centro Automotivo",
cidade: "Guarulhos",
quote: "Hoje todo o sistema está estruturado com backup em nuvem e funcionando perfeitamente.",
destaque: "Backup em nuvem implementado",
icone: "🚘"
},
{
id: 3,
cliente: "Toyota Arquitetura",
responsavel: "Elio Toyota",
segmento: "Arquitetura",
cidade: "Guarulhos",
quote: "Fui atendido prontamente, mesmo fora do horário, salvando um contrato importante.",
destaque: "Atendimento fora do horário",
icone: "🪵"
},
{
id: 4,
cliente: "R2 Car",
responsavel: "R2 Car Centro Automotivo",
segmento: "Pintura Automotiva",
cidade: "Guarulhos",
quote: "Em menos de uma hora todos os problemas foram resolvidos e tudo voltou a funcionar perfeitamente.",
destaque: "Resolvido em menos de 1 hora",
icone: "🚗"
},
{
id: 5,
cliente: "Simpercom Impermeabilizações",
responsavel: "João de Paula",
segmento: "Impermeabilização",
cidade: "Guarulhos",
quote: "O problema foi resolvido com excelência, fortalecendo ainda mais nossa parceria.",
destaque: "Resolvido com excelência",
icone: "🧱"
},
{
id: 6,
cliente: "Summa Desenvolvimento Humano",
responsavel: "Silvia Pedrosa Luiz",
segmento: "Coaching",
cidade: "São Paulo",
quote: "Os problemas foram resolvidos com rapidez e eficiência, mesmo para quem não entende de tecnologia.",
destaque: "Rapidez e eficiência",
icone: "🧠"
},
{
id: 7,
cliente: "Visão Contabilidade",
responsavel: "Antonio Gonçalves",
segmento: "Contabilidade",
cidade: "Guarulhos",
quote: "Passei a indicar os serviços com total confiança pela qualidade e agilidade.",
destaque: "Total confiança",
icone: "📊"
},
{
id: 8,
cliente: "SEG1 Corretora de Seguros",
responsavel: "Jorge Luiz Braga",
segmento: "Seguros",
cidade: "Guarulhos",
quote: "Melhoramos todos os computadores com apenas 10% do investimento necessário.",
destaque: "90% de economia",
icone: "🛡️"
},
{
id: 9,
cliente: "Apoio 24 Horas",
responsavel: "Roberto",
cargo: "Sócio Proprietário",
segmento: "Segurança / Monitoramento",
cidade: "Guarulhos",
quote: "Garantimos a operação 24h mesmo com falhas de internet e energia, graças à estrutura implementada pela Avanzato.",
destaque: "Operação 24h garantida",
icone: "🛡️"
},
{
id: 10,
cliente: "Lucio Seguros",
responsavel: "Lucio Benevenuto",
segmento: "Seguros",
cidade: "Guarulhos",
quote: "O equipamento ganhou performance e o atendimento foi rápido e eficiente.",
destaque: "Performance melhorada",
icone: "🛡️"
},
{
id: 11,
cliente: "Caroni Reis Advogados",
responsavel: "Jorge Paulo Caroni Reis",
segmento: "Advocacia",
cidade: "Guarulhos",
quote: "Fui atendido com dedicação e profissionalismo, sempre dentro do prazo e orçamento.",
destaque: "Dentro do prazo",
icone: "⚖️"
},
{
id: 12,
cliente: "Trilha Empregos",
responsavel: "Suelia Luz",
segmento: "Recrutamento",
cidade: "Guarulhos",
quote: "Superou minhas expectativas com um atendimento atencioso, competente e eficiente.",
destaque: "Superou expectativas",
icone: "🧩"
}
];
// Lista de empresas que confiam na Avanzato (logos/nomes no final da seção)
const empresasQueConfiam = [
"Apoio24horas",
"GateOneServitel",
"Alamo",
"Quantica",
"Mourad Nadi",
"RMA",
"Ganiko",
"Dcarvalho",
"Divas Car",
"Thalls",
"Garuppy",
"Moraes",
"Dellacont",
"Madri",
"EFLAW",
"BST Security",
"Piso.com",
"RollPrime"
];
// Schema.org JSON-LD para SEO
const generateSchemaOrg = () => {
const reviews = testimonials.map(t => ({
"@type": "Review",
"author": {
"@type": "Person",
"name": t.responsavel
},
"reviewRating": {
"@type": "Rating",
"ratingValue": 5,
"bestRating": 5
},
"reviewBody": t.quote,
"publisher": {
"@type": "Organization",
"name": t.cliente
}
}));
return {
"@context": "https://schema.org",
"@type": "Organization",
"name": "Avanzato Tecnologia",
"url": "https://avanzato.com.br",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "5",
"bestRating": "5",
"ratingCount": String(reviews.length),
"reviewCount": String(reviews.length)
},
"review": reviews
};
};
const TestimonialCard = ({ testimonial }: { testimonial: Testimonial }) => {
return (
<div className="testimonial-card bg-[#1a1a1a] rounded-2xl p-6 border border-white/5 hover:border-[#cbf400]/30 transition-all duration-300 h-full flex flex-col">
{/* Icon and stars */}
<div className="flex items-center justify-between mb-4">
<span className="text-2xl">{testimonial.icone}</span>
<div className="flex gap-0.5">
{[...Array(5)].map((_, i) => (
<Star key={i} className="w-4 h-4 text-[#cbf400] fill-[#cbf400]" />
))}
</div>
</div>
{/* Quote */}
<blockquote className="text-gray-300 text-sm leading-relaxed mb-4 flex-1">
"{testimonial.quote}"
</blockquote>
{/* Destaque badge */}
<div className="mb-4">
<span className="inline-block px-3 py-1 bg-[#cbf400]/10 text-[#cbf400] text-xs font-medium rounded-full border border-[#cbf400]/20">
{testimonial.destaque}
</span>
</div>
{/* Client info */}
<div className="flex items-center gap-3 pt-4 border-t border-white/5">
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-[#cbf400]/20 to-[#cbf400]/5 flex items-center justify-center text-[#cbf400] font-bold">
{testimonial.responsavel.charAt(0)}
</div>
<div className="min-w-0">
<p className="text-white font-semibold text-sm truncate">{testimonial.responsavel}</p>
<div className="flex items-center gap-2 text-gray-500 text-xs">
<Building2 className="w-3 h-3 flex-shrink-0" />
<span className="truncate">{testimonial.cliente}</span>
</div>
<div className="flex items-center gap-2 text-gray-600 text-xs">
<MapPin className="w-3 h-3 flex-shrink-0" />
<span>{testimonial.cidade}</span>
</div>
</div>
</div>
</div>
);
};
const Testimonials = () => {
const sectionRef = useRef<HTMLDivElement>(null);
const titleRef = useRef<HTMLDivElement>(null);
const cardsRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const ctx = gsap.context(() => {
gsap.fromTo(
titleRef.current,
{ y: 50, opacity: 0 },
{
y: 0,
opacity: 1,
duration: 0.8,
ease: 'expo.out',
scrollTrigger: {
trigger: titleRef.current,
start: 'top 80%',
toggleActions: 'play none none reverse',
},
}
);
const cards = cardsRef.current?.querySelectorAll('.testimonial-card');
if (cards) {
gsap.fromTo(
cards,
{ y: 60, opacity: 0 },
{
y: 0,
opacity: 1,
duration: 0.7,
stagger: 0.08,
ease: 'expo.out',
scrollTrigger: {
trigger: cardsRef.current,
start: 'top 80%',
toggleActions: 'play none none reverse',
},
}
);
}
}, sectionRef);
return () => ctx.revert();
}, []);
const schemaData = generateSchemaOrg();
return (
<section
id="depoimentos"
ref={sectionRef}
className="section-padding bg-[#0e0e0e] relative overflow-hidden"
>
{/* Schema.org JSON-LD */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaData) }}
/>
{/* Background decoration */}
<div className="absolute top-0 left-0 w-[500px] h-[500px] bg-[#cbf400]/5 rounded-full blur-3xl -translate-y-1/2 -translate-x-1/2" />
<div className="absolute bottom-0 right-0 w-[500px] h-[500px] bg-[#cbf400]/5 rounded-full blur-3xl translate-y-1/2 translate-x-1/2" />
<div className="container-custom relative z-10">
{/* Section header */}
<div ref={titleRef} className="text-center max-w-3xl mx-auto mb-16">
<span className="inline-block px-4 py-2 rounded-full bg-[#cbf400]/10 text-[#cbf400] text-sm font-semibold mb-4 border border-[#cbf400]/20">
Depoimentos
</span>
<h2 className="text-3xl md:text-4xl lg:text-5xl font-black text-white mb-4">
O que nossos <span className="text-gradient">clientes dizem</span>
</h2>
<p className="text-gray-400 text-lg">
Mais de 500 empresas confiam na Avanzato para cuidar da sua tecnologia.
Veja o que dizem sobre nossos serviços.
</p>
</div>
{/* Stats bar */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-6 mb-16">
{[
{ valor: "500+", label: "Clientes atendidos" },
{ valor: "11", label: "Anos de experiência" },
{ valor: "4.9", label: "Nota média" },
{ valor: "98%", label: "Taxa de satisfação" },
].map((stat, i) => (
<div key={i} className="text-center bg-[#1a1a1a] rounded-xl p-6 border border-white/5">
<div className="text-3xl md:text-4xl font-black text-[#cbf400] mb-1">{stat.valor}</div>
<div className="text-gray-500 text-sm">{stat.label}</div>
</div>
))}
</div>
{/* Testimonials grid */}
<div
ref={cardsRef}
className="grid md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5"
>
{testimonials.map((testimonial) => (
<TestimonialCard key={testimonial.id} testimonial={testimonial} />
))}
</div>
{/* Client logos section */}
<div className="mt-20">
<p className="text-center text-gray-500 text-sm mb-8 uppercase tracking-wider">
Empresas que confiam na Avanzato
</p>
<div className="flex flex-wrap justify-center items-center gap-x-8 gap-y-4 opacity-60">
{empresasQueConfiam.map((empresa, i) => (
<span key={i} className="text-gray-400 font-medium text-sm hover:text-[#cbf400] transition-colors">
{empresa}
</span>
))}
</div>
</div>
</div>
</section>
);
};
export default Testimonials;