Issues git resolved
This commit is contained in:
@@ -25,16 +25,16 @@ const BackToTop: React.FC = () => {
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{isVisible && (
|
||||
<motion.button
|
||||
initial={{ opacity: 0, scale: 0.8, y: 20 }}
|
||||
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||
exit={{ opacity: 0, scale: 0.8, y: 20 }}
|
||||
whileHover={{ scale: 1.1, backgroundColor: "#3b82f6" }}
|
||||
whileTap={{ scale: 0.9 }}
|
||||
onClick={scrollToTop}
|
||||
className="fixed bottom-8 right-8 z-50 w-12 h-12 flex items-center justify-center rounded-full bg-black dark:bg-white text-white dark:text-black shadow-lg border border-gray-700 dark:border-gray-200 transition-colors"
|
||||
aria-label="Back to top"
|
||||
>
|
||||
<motion.button
|
||||
initial={{ opacity: 0, scale: 0.8, y: 20 }}
|
||||
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||
exit={{ opacity: 0, scale: 0.8, y: 20 }}
|
||||
whileHover={{ scale: 1.1 }}
|
||||
whileTap={{ scale: 0.9 }}
|
||||
onClick={scrollToTop}
|
||||
className="selection-inverse fixed bottom-8 right-8 z-50 w-12 h-12 flex items-center justify-center rounded-full bg-black dark:bg-white text-white dark:text-black shadow-lg border border-gray-700 dark:border-gray-200 transition-colors"
|
||||
aria-label="Back to top"
|
||||
>
|
||||
<span className="material-symbols-outlined text-2xl">arrow_upward</span>
|
||||
</motion.button>
|
||||
)}
|
||||
@@ -42,4 +42,4 @@ const BackToTop: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default BackToTop;
|
||||
export default BackToTop;
|
||||
|
||||
@@ -3,15 +3,15 @@ import { motion } from 'framer-motion';
|
||||
import gsap from 'gsap';
|
||||
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { blogPostData } from '../src/data/seoData';
|
||||
import { orderedBlogPostData } from '../src/data/seoData';
|
||||
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
const posts = blogPostData
|
||||
const posts = orderedBlogPostData
|
||||
.filter((post) => !post.redirect)
|
||||
.slice(0, 3)
|
||||
.map((post) => ({
|
||||
image: post.image || '/images/blog/business-email-comparison-new.png',
|
||||
image: post.image || '/images/blog/business-email-comparison-new.webp',
|
||||
category: post.category === 'authority' ? 'IT Insights' : 'Local Services',
|
||||
title: post.h1,
|
||||
excerpt: post.description,
|
||||
|
||||
@@ -31,18 +31,18 @@ const CTA: React.FC = () => {
|
||||
transition={{ delay: 0.2 }}
|
||||
className="flex flex-col sm:flex-row gap-4 justify-center items-center"
|
||||
>
|
||||
<Link
|
||||
to="/contact"
|
||||
className="px-8 py-4 bg-black dark:bg-white text-white dark:text-black rounded-full font-medium transition-all hover:scale-105 shadow-lg w-full sm:w-auto"
|
||||
>
|
||||
Book a 20-minute assessment
|
||||
</Link>
|
||||
<Link
|
||||
to="/contact"
|
||||
className="px-8 py-4 bg-gray-100 dark:bg-white/10 text-gray-900 dark:text-white rounded-full font-medium transition-all hover:bg-gray-200 dark:hover:bg-white/20 w-full sm:w-auto"
|
||||
>
|
||||
Send a message
|
||||
</Link>
|
||||
<Link
|
||||
to="/contact"
|
||||
className="selection-inverse px-8 py-4 bg-black dark:bg-white text-white dark:text-black rounded-full font-medium transition-all hover:scale-105 shadow-lg w-full sm:w-auto"
|
||||
>
|
||||
Book a 20-minute assessment
|
||||
</Link>
|
||||
<Link
|
||||
to="/contact"
|
||||
className="selection-inverse px-8 py-4 bg-gray-100 dark:bg-white/10 text-gray-900 dark:text-white rounded-full font-medium transition-all hover:bg-gray-200 dark:hover:bg-white/20 w-full sm:w-auto"
|
||||
>
|
||||
Send a message
|
||||
</Link>
|
||||
<a
|
||||
href="tel:+13617658400"
|
||||
className="text-sm text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white transition-colors mt-2"
|
||||
|
||||
@@ -1,113 +1,136 @@
|
||||
import React from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const Contact: React.FC = () => {
|
||||
return (
|
||||
<motion.section
|
||||
id="contact"
|
||||
initial={{ opacity: 0, y: 50 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
transition={{ duration: 0.8, ease: "easeOut" }}
|
||||
className="py-24 bg-white dark:bg-[#0f0f0f] border-t border-gray-100 dark:border-white/5"
|
||||
>
|
||||
<div className="max-w-3xl mx-auto px-6">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="text-center mb-12"
|
||||
>
|
||||
<h2 className="font-display text-4xl md:text-5xl font-medium mb-6 text-gray-900 dark:text-white">
|
||||
Get in Touch
|
||||
</h2>
|
||||
<p className="text-gray-600 dark:text-gray-400 text-lg">
|
||||
We're here to help you with all your IT needs.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<motion.form
|
||||
initial={{ opacity: 0 }}
|
||||
whileInView={{ opacity: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.2 }}
|
||||
className="space-y-6"
|
||||
>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label htmlFor="name" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Name *</label>
|
||||
<motion.input
|
||||
whileFocus={{ scale: 1.01, borderColor: "#3b82f6" }}
|
||||
transition={{ duration: 0.2 }}
|
||||
type="text"
|
||||
id="name"
|
||||
placeholder="Your Name"
|
||||
required
|
||||
className="w-full px-4 py-3 rounded-lg bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400/20 focus:border-blue-500 outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="email" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Email *</label>
|
||||
<motion.input
|
||||
whileFocus={{ scale: 1.01, borderColor: "#3b82f6" }}
|
||||
transition={{ duration: 0.2 }}
|
||||
type="email"
|
||||
id="email"
|
||||
placeholder="Your Email"
|
||||
required
|
||||
className="w-full px-4 py-3 rounded-lg bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400/20 focus:border-blue-500 outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label htmlFor="phone" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Phone (optional)</label>
|
||||
<motion.input
|
||||
whileFocus={{ scale: 1.01, borderColor: "#3b82f6" }}
|
||||
transition={{ duration: 0.2 }}
|
||||
type="tel"
|
||||
id="phone"
|
||||
placeholder="Your Phone Number"
|
||||
className="w-full px-4 py-3 rounded-lg bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400/20 focus:border-blue-500 outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="company" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Company (optional)</label>
|
||||
<motion.input
|
||||
whileFocus={{ scale: 1.01, borderColor: "#3b82f6" }}
|
||||
transition={{ duration: 0.2 }}
|
||||
type="text"
|
||||
id="company"
|
||||
placeholder="Your Company Name"
|
||||
className="w-full px-4 py-3 rounded-lg bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400/20 focus:border-blue-500 outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="message" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Message *</label>
|
||||
<motion.textarea
|
||||
whileFocus={{ scale: 1.01, borderColor: "#3b82f6" }}
|
||||
transition={{ duration: 0.2 }}
|
||||
id="message"
|
||||
placeholder="Your Message"
|
||||
required
|
||||
className="w-full px-4 py-3 rounded-lg bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400/20 focus:border-blue-500 outline-none transition-all h-32 resize-none"
|
||||
></motion.textarea>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<motion.button
|
||||
type="submit"
|
||||
whileHover={{ scale: 1.05, backgroundColor: "#3b82f6", color: "#ffffff", border: "none" }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
className="px-8 py-3 bg-black dark:bg-white text-white dark:text-black rounded-full font-medium transition-all duration-300 w-full md:w-auto shadow-lg"
|
||||
>
|
||||
Send Message
|
||||
</motion.button>
|
||||
</div>
|
||||
</motion.form>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Contact;
|
||||
import React from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
import { useContactForm } from '../src/hooks/useContactForm';
|
||||
|
||||
const Contact: React.FC = () => {
|
||||
const { errorMessage, hasError, isSubmitted, isSubmitting, resetFeedback, submitContactForm } = useContactForm();
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
id="contact"
|
||||
initial={{ opacity: 0, y: 50 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
transition={{ duration: 0.8, ease: "easeOut" }}
|
||||
className="py-24 bg-white dark:bg-[#0f0f0f] border-t border-gray-100 dark:border-white/5"
|
||||
>
|
||||
<div className="max-w-3xl mx-auto px-6">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="text-center mb-12"
|
||||
>
|
||||
<h2 className="font-display text-4xl md:text-5xl font-medium mb-6 text-gray-900 dark:text-white">
|
||||
Get in Touch
|
||||
</h2>
|
||||
<p className="text-gray-600 dark:text-gray-400 text-lg">
|
||||
We're here to help you with all your IT needs.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<motion.form
|
||||
initial={{ opacity: 0 }}
|
||||
whileInView={{ opacity: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.2 }}
|
||||
className="space-y-6"
|
||||
onChange={resetFeedback}
|
||||
onSubmit={submitContactForm}
|
||||
>
|
||||
<input type="text" name="website" tabIndex={-1} autoComplete="off" className="hidden" aria-hidden="true" />
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label htmlFor="contact-name" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Name *</label>
|
||||
<motion.input
|
||||
whileFocus={{ scale: 1.01, borderColor: "#3b82f6" }}
|
||||
transition={{ duration: 0.2 }}
|
||||
type="text"
|
||||
id="contact-name"
|
||||
name="name"
|
||||
placeholder="Your Name"
|
||||
required
|
||||
className="w-full px-4 py-3 rounded-lg bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400/20 focus:border-blue-500 outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="contact-email" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Email *</label>
|
||||
<motion.input
|
||||
whileFocus={{ scale: 1.01, borderColor: "#3b82f6" }}
|
||||
transition={{ duration: 0.2 }}
|
||||
type="email"
|
||||
id="contact-email"
|
||||
name="email"
|
||||
placeholder="Your Email"
|
||||
required
|
||||
className="w-full px-4 py-3 rounded-lg bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400/20 focus:border-blue-500 outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label htmlFor="contact-phone" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Phone (optional)</label>
|
||||
<motion.input
|
||||
whileFocus={{ scale: 1.01, borderColor: "#3b82f6" }}
|
||||
transition={{ duration: 0.2 }}
|
||||
type="tel"
|
||||
id="contact-phone"
|
||||
name="phone"
|
||||
placeholder="Your Phone Number"
|
||||
className="w-full px-4 py-3 rounded-lg bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400/20 focus:border-blue-500 outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="contact-company" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Company (optional)</label>
|
||||
<motion.input
|
||||
whileFocus={{ scale: 1.01, borderColor: "#3b82f6" }}
|
||||
transition={{ duration: 0.2 }}
|
||||
type="text"
|
||||
id="contact-company"
|
||||
name="company"
|
||||
placeholder="Your Company Name"
|
||||
className="w-full px-4 py-3 rounded-lg bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400/20 focus:border-blue-500 outline-none transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="contact-message" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Message *</label>
|
||||
<motion.textarea
|
||||
whileFocus={{ scale: 1.01, borderColor: "#3b82f6" }}
|
||||
transition={{ duration: 0.2 }}
|
||||
id="contact-message"
|
||||
name="message"
|
||||
placeholder="Your Message"
|
||||
required
|
||||
className="w-full px-4 py-3 rounded-lg bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400/20 focus:border-blue-500 outline-none transition-all h-32 resize-none"
|
||||
></motion.textarea>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<motion.button
|
||||
type="submit"
|
||||
whileHover={{ scale: isSubmitting ? 1 : 1.05 }}
|
||||
whileTap={{ scale: isSubmitting ? 1 : 0.95 }}
|
||||
disabled={isSubmitting}
|
||||
className="selection-inverse px-8 py-3 bg-black dark:bg-white text-white dark:text-black rounded-full font-medium transition-all duration-300 w-full md:w-auto shadow-lg disabled:cursor-not-allowed disabled:opacity-70"
|
||||
>
|
||||
{isSubmitting ? 'Sending...' : 'Send Message'}
|
||||
</motion.button>
|
||||
</div>
|
||||
{isSubmitted && (
|
||||
<p className="text-sm text-green-600 dark:text-green-400">
|
||||
Thanks. Your message was sent successfully.
|
||||
</p>
|
||||
)}
|
||||
{hasError && (
|
||||
<p className="text-sm text-red-600 dark:text-red-400">
|
||||
{errorMessage}
|
||||
</p>
|
||||
)}
|
||||
</motion.form>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Contact;
|
||||
|
||||
@@ -13,7 +13,7 @@ const Footer: React.FC = () => {
|
||||
<span className="font-display font-bold text-lg tracking-tight text-gray-900 dark:text-white">Bay Area IT</span>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400 max-w-xs mb-6">
|
||||
Providing reliable IT services and practical technology support to the Coastal Bend community for over 25 years.
|
||||
Providing reliable IT services and practical technology support to the Coastal Bend community for over 30 years.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
<a href="tel:+13617658400" className="transition-colors hover:text-gray-900 dark:hover:text-white">
|
||||
@@ -29,11 +29,13 @@ const Footer: React.FC = () => {
|
||||
<h4 className="text-sm font-bold text-gray-900 dark:text-white mb-6 uppercase tracking-wider">Services</h4>
|
||||
<ul className="space-y-4 text-sm text-gray-600 dark:text-gray-400">
|
||||
{[
|
||||
{ label: 'Bay Area Email Services', to: '/services/business-email-services' },
|
||||
{ label: 'IT Help Desk', to: '/services/it-help-desk' },
|
||||
{ label: 'Computer Support', to: '/services/computer-support' },
|
||||
{ label: 'Business Email', to: '/services/business-email-services' },
|
||||
{ label: 'Domain & DNS', to: '/services/domain-registration-dns-support' },
|
||||
{ label: 'New/Refurbished Desktop Hardware', to: '/services/computer-support' },
|
||||
{ label: 'Printer & Scanner Installation', to: '/services/printer-scanner-installation' },
|
||||
{ label: 'Web Design', to: '/services/web-design-corpus-christi' },
|
||||
{ label: 'Shared Drive', to: '/services/shared-drive' },
|
||||
{ label: 'Network Infrastructure Support', to: '/services/network-infrastructure-support' },
|
||||
].map((item) => (
|
||||
<li key={item.label}>
|
||||
<motion.div whileHover={{ x: 5 }} className="inline-block">
|
||||
|
||||
@@ -110,13 +110,13 @@ const Hero: React.FC = () => {
|
||||
<div className="relative z-10 text-center max-w-4xl px-6">
|
||||
<div className="hero-stagger flex items-center justify-center gap-2 mb-6">
|
||||
<span className="h-px w-8 bg-gray-400 dark:bg-gray-500"></span>
|
||||
<span className="text-xs uppercase tracking-[0.2em] text-gray-600 dark:text-gray-400 font-medium">Serving the Coastal Bend since 2000</span>
|
||||
<span className="text-xs uppercase tracking-[0.2em] text-gray-600 dark:text-gray-400 font-medium">Serving the Coastal Bend since 1996</span>
|
||||
<span className="h-px w-8 bg-gray-400 dark:bg-gray-500"></span>
|
||||
</div>
|
||||
|
||||
<h1 className="hero-stagger font-display text-5xl md:text-7xl lg:text-8xl font-medium tracking-tighter leading-[1.1] mb-8 text-gray-900 dark:text-white">
|
||||
Reliable IT Services<br />
|
||||
<span className="text-gray-500 dark:text-gray-500">for Over 25 Years</span>
|
||||
<span className="text-gray-500 dark:text-gray-500">for Over 30 Years</span>
|
||||
</h1>
|
||||
|
||||
<p className="hero-stagger text-lg md:text-xl text-gray-600 dark:text-gray-300 max-w-2xl mx-auto mb-10 font-light leading-relaxed">
|
||||
@@ -124,21 +124,21 @@ const Hero: React.FC = () => {
|
||||
</p>
|
||||
|
||||
<div className="hero-stagger flex flex-col sm:flex-row items-center justify-center gap-4">
|
||||
<motion.a
|
||||
href="#services"
|
||||
className="px-8 py-3 bg-black dark:bg-white text-white dark:text-black rounded-full font-medium"
|
||||
whileHover={{ scale: 1.05, backgroundColor: "#3b82f6", color: "#ffffff" }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
>
|
||||
IT Services
|
||||
</motion.a>
|
||||
<motion.a
|
||||
href="#contact"
|
||||
className="px-8 py-3 bg-transparent border border-gray-300 dark:border-white/20 text-gray-900 dark:text-white rounded-full font-medium"
|
||||
whileHover={{ scale: 1.05, backgroundColor: "rgba(255,255,255,0.1)", borderColor: "#ffffff" }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
>
|
||||
Get in Touch
|
||||
<motion.a
|
||||
href="#services"
|
||||
className="selection-inverse px-8 py-3 bg-black dark:bg-white text-white dark:text-black rounded-full font-medium"
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
>
|
||||
IT Services
|
||||
</motion.a>
|
||||
<motion.a
|
||||
href="/contact"
|
||||
className="px-8 py-3 bg-transparent border border-gray-300 dark:border-white/20 text-gray-900 dark:text-white rounded-full font-medium"
|
||||
whileHover={{ scale: 1.05, backgroundColor: "rgba(255,255,255,0.1)", borderColor: "#ffffff" }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
>
|
||||
Get in Touch
|
||||
</motion.a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -34,12 +34,12 @@ const Navbar: React.FC = () => {
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Link
|
||||
to="/contact"
|
||||
className="hidden md:inline-flex items-center px-4 py-1.5 bg-black dark:bg-white text-white dark:text-black rounded-full text-sm font-medium hover:bg-gray-800 dark:hover:bg-gray-100 transition-colors"
|
||||
>
|
||||
Get IT Support
|
||||
</Link>
|
||||
<Link
|
||||
to="/contact"
|
||||
className="selection-inverse hidden md:inline-flex items-center px-4 py-1.5 bg-black dark:bg-white text-white dark:text-black rounded-full text-sm font-medium hover:bg-gray-800 dark:hover:bg-gray-100 transition-colors"
|
||||
>
|
||||
Get IT Support
|
||||
</Link>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
|
||||
@@ -7,32 +7,23 @@ import { Link } from 'react-router-dom';
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
const servicesData = [
|
||||
{
|
||||
id: 1,
|
||||
category: 'Web Services',
|
||||
title: 'Web Design',
|
||||
description: 'Professional websites with domain registration and DNS support to give your business a clean, reliable online presence.',
|
||||
icon: 'language',
|
||||
image: '/assets/services/business-it.webp',
|
||||
href: '/services/web-design-corpus-christi'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
category: 'Web Services',
|
||||
title: 'Bay Area Email Services',
|
||||
description: 'Enterprise cloud email with 99.99% uptime, local Texas support, 25 GB mailboxes, and business-grade delivery for $5 per inbox.',
|
||||
icon: 'mail',
|
||||
image: '/assets/services/business-it.webp',
|
||||
image: '/assets/services/business-email-services.webp',
|
||||
href: '/services/business-email-services'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
id: 7,
|
||||
category: 'IT Infrastructure',
|
||||
title: 'Printer & Scanner Installation',
|
||||
description: 'Professional installation and configuration of printers and scanners to ensure seamless integration into your workflow.',
|
||||
icon: 'print',
|
||||
image: '/assets/services/printer-scanner.webp',
|
||||
href: '/services'
|
||||
title: 'IT Help Desk',
|
||||
description: 'Fast and reliable help desk support for employees, resolving technical issues remotely or on-site.',
|
||||
icon: 'support_agent',
|
||||
image: '/assets/services/help-desk.webp',
|
||||
href: '/services/it-help-desk'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
@@ -44,13 +35,22 @@ const servicesData = [
|
||||
href: '/services/computer-support'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
category: 'Networking',
|
||||
title: 'Network Infrastructure Support',
|
||||
description: 'Robust network solutions to ensure connectivity, security, and efficiency, including routers, access points, and switches.',
|
||||
icon: 'lan',
|
||||
image: '/assets/services/network-infrastructure.webp',
|
||||
href: '/services'
|
||||
id: 3,
|
||||
category: 'IT Infrastructure',
|
||||
title: 'Printer & Scanner Installation',
|
||||
description: 'Professional installation and configuration of printers and scanners to ensure seamless integration into your workflow.',
|
||||
icon: 'print',
|
||||
image: '/assets/services/printer-scanner.webp',
|
||||
href: '/services/printer-scanner-installation'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
category: 'Web Services',
|
||||
title: 'Web Design',
|
||||
description: 'Professional websites with domain registration and DNS support to give your business a clean, reliable online presence.',
|
||||
icon: 'language',
|
||||
image: '/assets/services/business-it.webp',
|
||||
href: '/services/web-design-corpus-christi'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
@@ -59,16 +59,16 @@ const servicesData = [
|
||||
description: 'Setup and management of shared drive solutions so your team can store, access, and organize files reliably.',
|
||||
icon: 'storage',
|
||||
image: '/assets/services/nas-storage.webp',
|
||||
href: '/services'
|
||||
href: '/services/shared-drive'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
category: 'IT Infrastructure',
|
||||
title: 'IT Help Desk',
|
||||
description: 'Fast and reliable help desk support for employees, resolving technical issues remotely or on-site.',
|
||||
icon: 'support_agent',
|
||||
image: '/assets/services/help-desk.webp',
|
||||
href: '/services/it-help-desk'
|
||||
id: 5,
|
||||
category: 'Networking',
|
||||
title: 'Network Infrastructure Support',
|
||||
description: 'Robust network solutions to ensure connectivity, security, and efficiency, including routers, access points, and switches.',
|
||||
icon: 'lan',
|
||||
image: '/assets/services/network-infrastructure.webp',
|
||||
href: '/services/network-infrastructure-support'
|
||||
}
|
||||
];
|
||||
|
||||
@@ -203,14 +203,14 @@ const Services: React.FC<ServicesProps> = ({ preview = false, featuredIds }) =>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{isRestrictedView && (
|
||||
<div className="mt-12 text-center">
|
||||
<button
|
||||
onClick={() => setShowAll(true)}
|
||||
className="inline-flex items-center gap-2 px-8 py-3 bg-black dark:bg-white text-white dark:text-black rounded-full font-medium hover:bg-gray-800 dark:hover:bg-gray-200 transition-colors"
|
||||
>
|
||||
Show More Services <span className="material-symbols-outlined text-sm">expand_more</span>
|
||||
</button>
|
||||
{isRestrictedView && (
|
||||
<div className="mt-12 text-center">
|
||||
<button
|
||||
onClick={() => setShowAll(true)}
|
||||
className="selection-inverse inline-flex items-center gap-2 px-8 py-3 bg-black dark:bg-white text-white dark:text-black rounded-full font-medium hover:bg-gray-800 dark:hover:bg-gray-200 transition-colors"
|
||||
>
|
||||
Show More Services <span className="material-symbols-outlined text-sm">expand_more</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1,44 +1,86 @@
|
||||
import React from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const Testimonials: React.FC = () => {
|
||||
return (
|
||||
<section className="py-24 px-6 bg-background-light dark:bg-background-dark relative overflow-hidden bg-[radial-gradient(ellipse_80%_50%_at_50%_-20%,rgba(0,0,0,0.05),rgba(0,0,0,0))] dark:bg-[radial-gradient(ellipse_80%_50%_at_50%_-20%,rgba(255,255,255,0.05),rgba(255,255,255,0))]">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
viewport={{ once: true }}
|
||||
className="bg-white dark:bg-white/5 backdrop-blur-sm p-8 md:p-12 rounded-3xl border border-gray-200 dark:border-white/10 shadow-2xl relative"
|
||||
>
|
||||
{/* Quote Icon */}
|
||||
<div className="absolute top-8 right-8 text-blue-100 dark:text-white/5 select-none">
|
||||
<span className="material-symbols-outlined text-8xl">format_quote</span>
|
||||
</div>
|
||||
|
||||
<div className="flex text-yellow-400 mb-6 gap-1 relative z-10">
|
||||
{[1, 2, 3, 4, 5].map((star) => (
|
||||
<span key={star} className="material-symbols-outlined fill-current">star</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<blockquote className="text-xl md:text-2xl font-medium leading-relaxed text-gray-900 dark:text-white mb-8 relative z-10">
|
||||
"Bay Area IT transformed our IT infrastructure completely. Their proactive approach means we rarely have downtime, and when issues do arise, they're resolved quickly. Our team can focus on patient care instead of tech problems."
|
||||
</blockquote>
|
||||
|
||||
<div className="flex items-center gap-4 relative z-10">
|
||||
<div className="w-12 h-12 bg-black dark:bg-white rounded-full flex items-center justify-center text-white dark:text-black font-bold text-lg">
|
||||
SM
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-bold text-gray-900 dark:text-white">Sarah Martinez</div>
|
||||
<div className="text-sm text-gray-500 dark:text-gray-400">Operations Manager, Coastal Medical Group</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Testimonials;
|
||||
import React from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const testimonials = [
|
||||
{
|
||||
quote:
|
||||
"Bay Area Affiliates has been working on our office computers for years. They always go above and beyond to make sure we are back up and running smoothly. I wouldn't trust anyone but Elvin and Wallie to work on my computers. The absolute best in South Texas!",
|
||||
initials: 'SG',
|
||||
name: 'Stephanie Gomez',
|
||||
role: 'Sales Representative, J & B Pavelka Truck and Trailer Sales',
|
||||
layout: 'lg:col-span-5',
|
||||
},
|
||||
{
|
||||
quote:
|
||||
"We cannot say enough great things about the service Wallie and Elvin at Bay Area Affiliates, Inc. have provided to our firm for well over 15 years! They take care of all of our computer/networking/software/website needs so we don't have to worry about anything related to IT. Whenever we have any computer/software issues, need to add new equipment, install software/upgrades etc., they are always there for us and respond quickly to keep our system running safely and securely. But besides their solid technical skills and vast computer systems knowledge, they are an absolute pleasure to work with. I recommend them to all of my clients and friends. They are the BEST of the BEST!",
|
||||
initials: 'CB',
|
||||
name: 'Cheryl Brown',
|
||||
role: 'Owner & CPA, Hampton, Brown & Associates, P.C.',
|
||||
layout: 'lg:col-span-7',
|
||||
},
|
||||
{
|
||||
quote:
|
||||
'We have used Bay Area Affiliates for many years and could not be happier with the expertise and service we have received.',
|
||||
initials: 'GC',
|
||||
name: 'George Craig',
|
||||
role: 'President, SCI Security',
|
||||
layout: 'lg:col-span-6 lg:col-start-4',
|
||||
},
|
||||
];
|
||||
|
||||
const Testimonials: React.FC = () => {
|
||||
return (
|
||||
<section className="py-24 px-6 bg-background-light dark:bg-background-dark relative overflow-hidden bg-[radial-gradient(ellipse_80%_50%_at_50%_-20%,rgba(0,0,0,0.05),rgba(0,0,0,0))] dark:bg-[radial-gradient(ellipse_80%_50%_at_50%_-20%,rgba(255,255,255,0.05),rgba(255,255,255,0))]">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="text-center mb-12">
|
||||
<span className="inline-flex items-center gap-2 px-4 py-2 rounded-full border border-gray-200 dark:border-white/10 bg-white/80 dark:bg-white/5 text-xs font-semibold uppercase tracking-[0.2em] text-gray-500 dark:text-gray-400">
|
||||
Client Testimonials
|
||||
</span>
|
||||
<h2 className="mt-5 font-display text-3xl md:text-4xl text-gray-900 dark:text-white">
|
||||
Trusted by businesses who need IT that <span className="text-gray-500 dark:text-gray-400">actually shows up</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 lg:grid-cols-12">
|
||||
{testimonials.map((testimonial, index) => (
|
||||
<motion.div
|
||||
key={testimonial.name}
|
||||
initial={{ opacity: 0, y: 24 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: index * 0.1 }}
|
||||
className={`min-w-0 bg-white/90 dark:bg-white/5 backdrop-blur-sm p-8 rounded-3xl border border-gray-200 dark:border-white/10 shadow-[0_24px_80px_rgba(15,23,42,0.08)] dark:shadow-[0_24px_80px_rgba(0,0,0,0.28)] relative h-full overflow-hidden ${testimonial.layout}`}
|
||||
>
|
||||
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_right,rgba(59,130,246,0.12),transparent_30%)] dark:bg-[radial-gradient(circle_at_top_right,rgba(255,255,255,0.08),transparent_30%)] pointer-events-none" />
|
||||
<div className="absolute top-6 right-6 text-blue-100 dark:text-white/5 select-none">
|
||||
<span className="material-symbols-outlined text-7xl">format_quote</span>
|
||||
</div>
|
||||
|
||||
<div className="flex text-yellow-400 mb-6 gap-1 relative z-10">
|
||||
{[1, 2, 3, 4, 5].map((star) => (
|
||||
<span key={star} className="material-symbols-outlined fill-current">star</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<blockquote className="text-base md:text-lg font-medium leading-relaxed text-gray-900 dark:text-white mb-8 relative z-10 break-words [overflow-wrap:anywhere]">
|
||||
"{testimonial.quote}"
|
||||
</blockquote>
|
||||
|
||||
<div className="flex items-center gap-4 relative z-10 mt-auto">
|
||||
<div className="w-12 h-12 shrink-0 bg-black dark:bg-white rounded-full flex items-center justify-center text-white dark:text-black font-bold text-lg">
|
||||
{testimonial.initials}
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<div className="font-bold text-gray-900 dark:text-white">{testimonial.name}</div>
|
||||
<div className="text-sm text-gray-500 dark:text-gray-400 break-words [overflow-wrap:anywhere]">{testimonial.role}</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Testimonials;
|
||||
|
||||
Reference in New Issue
Block a user