fix(ui): UI fixes across header, contact, home, about, support, services, industries (#132 #133 #134 #154 #165 #172 #173)

This commit is contained in:
null 2026-05-18 13:12:18 -05:00
parent fdc6eaeab5
commit de61d5e625
13 changed files with 364 additions and 407 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "queuenorth-website", "name": "queuenorth-website",
"private": true, "private": true,
"version": "0.7.2", "version": "0.7.3",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "concurrently \"vite\" \"node server/index.js\"", "dev": "concurrently \"vite\" \"node server/index.js\"",

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

BIN
public/assets/wireless.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View File

@ -74,7 +74,7 @@ const Header = () => {
</Link> </Link>
{/* Services Dropdown */} {/* Services Dropdown */}
{link.name === 'Services' && ( {link.name === 'Services' && (
<div className="absolute top-full left-0 w-64 bg-white rounded-lg shadow-xl border border-gray-200 hidden group-hover:block pt-2"> <div className="absolute top-full left-0 w-64 bg-white rounded-md shadow-xl border border-gray-200 hidden group-hover:block pt-2">
<div className="p-2"> <div className="p-2">
{serviceLinks.map((service) => ( {serviceLinks.map((service) => (
<Link <Link
@ -90,7 +90,7 @@ const Header = () => {
)} )}
{/* Industries Dropdown */} {/* Industries Dropdown */}
{link.name === 'Industries' && ( {link.name === 'Industries' && (
<div className="absolute top-full left-0 w-64 bg-white rounded-lg shadow-xl border border-gray-200 hidden group-hover:block pt-2"> <div className="absolute top-full left-0 w-64 bg-white rounded-md shadow-xl border border-gray-200 hidden group-hover:block pt-2">
<div className="p-2"> <div className="p-2">
{industryLinks.map((industry) => ( {industryLinks.map((industry) => (
<Link <Link

View File

@ -4,7 +4,7 @@ const Card = React.forwardRef(
({ className = '', ...props }, ref) => ( ({ className = '', ...props }, ref) => (
<div <div
ref={ref} ref={ref}
className={`rounded-xl border border-border bg-card text-text shadow-sm ${className}`} className={`rounded-md border border-border bg-card text-text shadow-sm ${className}`}
{...props} {...props}
/> />
) )
@ -62,4 +62,4 @@ const CardFooter = React.forwardRef(
) )
CardFooter.displayName = 'CardFooter' CardFooter.displayName = 'CardFooter'
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }

View File

@ -99,7 +99,7 @@ We support Cisco Webex Contact Center, 8x8 Contact Center, and other leading pla
homeDesc: 'Bad cabling means dropped calls and slow networks. We build it right the first time.', homeDesc: 'Bad cabling means dropped calls and slow networks. We build it right the first time.',
fullDesc: 'Clean structured cabling that gives your business the physical foundation for reliable communication and growth.', fullDesc: 'Clean structured cabling that gives your business the physical foundation for reliable communication and growth.',
icon: 'link', icon: 'link',
image: '/assets/cabling.webp', image: '/assets/cabling-unsplash.jpg',
benefits: [ benefits: [
'Cat6/Cat6a and fiber optic installations', 'Cat6/Cat6a and fiber optic installations',
'Data center cabling solutions', 'Data center cabling solutions',
@ -120,6 +120,7 @@ We support Cisco Webex Contact Center, 8x8 Contact Center, and other leading pla
homeDesc: 'Wi-Fi that just works — everywhere in your building. No dead zones, no complaints.', homeDesc: 'Wi-Fi that just works — everywhere in your building. No dead zones, no complaints.',
fullDesc: 'Business Wi-Fi designed for usable coverage, dependable performance, and fewer support headaches across your environment.', fullDesc: 'Business Wi-Fi designed for usable coverage, dependable performance, and fewer support headaches across your environment.',
icon: 'wifi', icon: 'wifi',
image: '/assets/wireless.webp',
benefits: [ benefits: [
'Enterprise Wi-Fi design and deployment', 'Enterprise Wi-Fi design and deployment',
'High-density coverage solutions', 'High-density coverage solutions',
@ -140,7 +141,6 @@ We support Cisco Webex Contact Center, 8x8 Contact Center, and other leading pla
homeDesc: 'A network that doesn\'t go down when it matters. Secure, fast, and built for your workload.', homeDesc: 'A network that doesn\'t go down when it matters. Secure, fast, and built for your workload.',
fullDesc: 'Switching and routing built for stability, visibility, and secure local network performance.', fullDesc: 'Switching and routing built for stability, visibility, and secure local network performance.',
icon: 'network', icon: 'network',
image: '/assets/local-networking.webp',
benefits: [ benefits: [
'Enterprise-grade routing and switching', 'Enterprise-grade routing and switching',
'Network security and segmentation', 'Network security and segmentation',

View File

@ -29,8 +29,7 @@ const About = () => {
{/* Company Story */} {/* Company Story */}
<section className="bg-background py-16"> <section className="bg-background py-16">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12"> <div className="max-w-3xl">
<div>
<h2 className="text-3xl font-bold text-primary-navy mb-4">Our Story</h2> <h2 className="text-3xl font-bold text-primary-navy mb-4">Our Story</h2>
<p className="text-lg text-soft-text mb-6 leading-relaxed"> <p className="text-lg text-soft-text mb-6 leading-relaxed">
Founded by military veterans, Queue North Technologies began with a simple mission: help businesses navigate the complex world of communications technology. What started as a small team of communications specialists has grown into a full-service provider for SMB and enterprise organizations across multiple industries. Founded by military veterans, Queue North Technologies began with a simple mission: help businesses navigate the complex world of communications technology. What started as a small team of communications specialists has grown into a full-service provider for SMB and enterprise organizations across multiple industries.
@ -44,16 +43,6 @@ const About = () => {
<p className="text-lg text-soft-text mt-4 leading-relaxed"> <p className="text-lg text-soft-text mt-4 leading-relaxed">
We continue the mission bringing the same discipline, reliability, and commitment to every client relationship that we brought to our service. We continue the mission bringing the same discipline, reliability, and commitment to every client relationship that we brought to our service.
</p> </p>
</div>
<div>
<div className="rounded-xl overflow-hidden shadow-lg">
<img
src="/assets/about-image.webp"
alt="Compass representing Queue North's guiding philosophy"
className="w-full h-72 object-cover object-top"
/>
</div>
</div>
</div> </div>
</div> </div>
</section> </section>
@ -68,8 +57,8 @@ const About = () => {
</p> </p>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-4xl mx-auto"> <div className="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-4xl mx-auto">
<div className="bg-white/10 border border-white/20 rounded-xl p-8"> <div className="bg-white/10 border border-white/20 rounded-md p-8">
<div className="w-12 h-12 bg-primary-cyan/20 rounded-lg flex items-center justify-center mb-5"> <div className="w-12 h-12 bg-primary-cyan/20 rounded-md flex items-center justify-center mb-5">
<svg className="h-6 w-6 text-primary-cyan" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}> <svg className="h-6 w-6 text-primary-cyan" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
<rect x="7" y="7" width="10" height="10" rx="1" strokeLinejoin="round" /> <rect x="7" y="7" width="10" height="10" rx="1" strokeLinejoin="round" />
<path strokeLinecap="round" strokeLinejoin="round" d="M9 7V5M12 7V5M15 7V5M9 17v2M12 17v2M15 17v2M7 9H5M7 12H5M7 15H5M17 9h2M17 12h2M17 15h2" /> <path strokeLinecap="round" strokeLinejoin="round" d="M9 7V5M12 7V5M15 7V5M9 17v2M12 17v2M15 17v2M7 9H5M7 12H5M7 15H5M17 9h2M17 12h2M17 15h2" />
@ -80,8 +69,8 @@ const About = () => {
Rooted in technology that works proven, stable, and repeatable. We focus on environments that behave predictably in real production conditions. Rooted in technology that works proven, stable, and repeatable. We focus on environments that behave predictably in real production conditions.
</p> </p>
</div> </div>
<div className="bg-white/10 border border-white/20 rounded-xl p-8"> <div className="bg-white/10 border border-white/20 rounded-md p-8">
<div className="w-12 h-12 bg-primary-cyan/20 rounded-lg flex items-center justify-center mb-5"> <div className="w-12 h-12 bg-primary-cyan/20 rounded-md flex items-center justify-center mb-5">
<svg className="h-6 w-6 text-primary-cyan" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}> <svg className="h-6 w-6 text-primary-cyan" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M5 10l7-7m0 0l7 7m-7-7v18" /> <path strokeLinecap="round" strokeLinejoin="round" d="M5 10l7-7m0 0l7 7m-7-7v18" />
</svg> </svg>
@ -108,7 +97,7 @@ const About = () => {
{ title: 'Reliability', desc: 'When we say we will do something, we do it' }, { title: 'Reliability', desc: 'When we say we will do something, we do it' },
{ title: 'Support', desc: 'Our job doesn\'t end when installation completes' }, { title: 'Support', desc: 'Our job doesn\'t end when installation completes' },
].map((value, index) => ( ].map((value, index) => (
<div key={index} className="p-6 rounded-lg border border-border bg-card shadow-sm hover:shadow-md transition-shadow"> <div key={index} className="p-6 rounded-md border border-border bg-card shadow-sm hover:shadow-md transition-shadow">
<h3 className="text-xl font-semibold text-primary-navy mb-3">{value.title}</h3> <h3 className="text-xl font-semibold text-primary-navy mb-3">{value.title}</h3>
<p className="text-soft-text">{value.desc}</p> <p className="text-soft-text">{value.desc}</p>
</div> </div>
@ -132,7 +121,7 @@ const About = () => {
'Disaster Recovery Planning', 'Disaster Recovery Planning',
'24/7 Support & Monitoring', '24/7 Support & Monitoring',
].map((expertise, index) => ( ].map((expertise, index) => (
<div key={index} className="flex items-center gap-2 p-3 rounded-lg border border-border bg-card"> <div key={index} className="flex items-center gap-2 p-3 rounded-md border border-border bg-card">
<div className="h-5 w-5 rounded-full bg-primary-navy text-white flex items-center justify-center flex-shrink-0"> <div className="h-5 w-5 rounded-full bg-primary-navy text-white flex items-center justify-center flex-shrink-0">
<svg className="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg className="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M5 13l4 4L19 7" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M5 13l4 4L19 7" />

View File

@ -145,7 +145,7 @@ const Contact = () => {
</Helmet> </Helmet>
{/* Hero */} {/* Hero */}
<section className="bg-primary-navy py-16 lg:py-20"> <section className="bg-primary-navy py-12 lg:py-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Let's Talk</h1> <h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Let's Talk</h1>
<p className="text-xl text-white/70 max-w-2xl"> <p className="text-xl text-white/70 max-w-2xl">
@ -155,16 +155,16 @@ const Contact = () => {
</section> </section>
{/* Contact Body */} {/* Contact Body */}
<section className="bg-background py-16 lg:py-20"> <section className="bg-background py-12 lg:py-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-0 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 lg:grid-cols-5 rounded-2xl overflow-hidden shadow-xl border border-border"> <div className="grid grid-cols-1 lg:grid-cols-5 rounded-none sm:rounded-md overflow-hidden shadow-none sm:shadow-xl border-y sm:border border-border">
{/* Left: Info panel */} {/* Left: Info panel — order 2 on mobile so form appears first */}
<div className="lg:col-span-2 bg-primary-navy text-white p-8 lg:p-10 flex flex-col gap-10"> <div className="lg:col-span-2 order-2 lg:order-1 bg-primary-navy text-white p-8 lg:p-10 flex flex-col gap-10">
<div className="space-y-7"> <div className="space-y-7">
{contactDetails.map((item) => ( {contactDetails.map((item) => (
<div key={item.label} className="flex items-start gap-4"> <div key={item.label} className="flex items-start gap-4">
<div className="w-10 h-10 bg-white/10 rounded-lg flex items-center justify-center flex-shrink-0"> <div className="w-10 h-10 bg-white/10 rounded-md flex items-center justify-center flex-shrink-0">
{item.icon} {item.icon}
</div> </div>
<div> <div>
@ -192,8 +192,8 @@ const Contact = () => {
</div> </div>
</div> </div>
{/* Right: Form panel */} {/* Right: Form panel — order 1 on mobile so it appears first */}
<div className="lg:col-span-3 bg-white p-8 lg:p-10"> <div className="lg:col-span-3 order-1 lg:order-2 bg-white p-6 sm:p-8 lg:p-10">
<h2 className="text-2xl font-bold text-primary-navy mb-1">Send Us a Message</h2> <h2 className="text-2xl font-bold text-primary-navy mb-1">Send Us a Message</h2>
<p className="text-soft-text text-sm mb-8">We typically respond within one business day.</p> <p className="text-soft-text text-sm mb-8">We typically respond within one business day.</p>

View File

@ -1,10 +1,9 @@
import { Helmet } from 'react-helmet-async' import { Helmet } from 'react-helmet-async'
import { Button } from '@/components/ui/Button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/Card' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/Card'
import { services } from '@/data/services' import { services } from '@/data/services'
import { industries } from '@/data/industries' import { industries } from '@/data/industries'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { MapPin, MessageCircle, Users, LifeBuoy, GraduationCap, Link as LinkIcon, Wifi, Network, Headphones, UserCheck, Activity, ShieldCheck, HeartPulse, ShoppingCart, Factory, Landmark, Building2, Award } from 'lucide-react' import { ArrowRight, MapPin, MessageCircle, Users, LifeBuoy, GraduationCap, Link as LinkIcon, Wifi, Network, Headphones, UserCheck, Activity, ShieldCheck, HeartPulse, ShoppingCart, Factory, Landmark, Building2, Award } from 'lucide-react'
// Icon map for industries - converts icon string to lucide component // Icon map for industries - converts icon string to lucide component
const industryIcons = { const industryIcons = {
@ -71,183 +70,67 @@ const Home = () => {
<script type="application/ld+json">{JSON.stringify(localBusinessLd)}</script> <script type="application/ld+json">{JSON.stringify(localBusinessLd)}</script>
</Helmet> </Helmet>
{/* Hero Section */} {/* Hero Section */}
<section className="bg-gradient-to-br from-primary-navy via-primary-navy to-teal-900 text-white py-16 md:py-24"> <section className="relative isolate overflow-hidden bg-primary-navy text-white">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="absolute inset-0 -z-10">
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-12 items-center"> <img
<div className="flex flex-col gap-6 md:gap-8"> src="/assets/hero-tech.webp"
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold"> alt="Queue North technician working inside a communications rack"
Reliable Business Communications Without the Runaround className="h-full w-full object-cover object-center"
</h1> />
<p className="text-xl md:text-2xl text-section-alt max-w-2xl"> <div className="absolute inset-0 bg-primary-navy/65" />
We handle your phones, internet, and IT so you can focus on running your business. 8x8 Certified Partner with 25+ years of proven reliability. <div className="absolute inset-0 bg-gradient-to-r from-primary-navy via-primary-navy/90 to-primary-navy/25" />
</p>
<div className="flex flex-col sm:flex-row gap-4">
<Link to="/contact" className="inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 bg-white text-primary-navy hover:bg-gray-100 transition-colors" aria-label="Schedule a consultation">
Schedule Consultation
</Link>
<Link to="/services" className="inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 border border-white text-white hover:bg-white/10 transition-colors" aria-label="View our services">
View Services
</Link>
</div>
<div className="flex flex-wrap gap-4">
<div className="flex items-center gap-2 px-4 py-2 bg-white/20 rounded-lg text-sm font-medium">
<img src="/assets/8x8_Logo_White.svg" alt="8x8 Certified Partner logo" className="h-5 w-5" />
<span>8x8 Certified Partner</span>
</div>
<div className="flex items-center gap-2 px-4 py-2 bg-white/20 rounded-lg text-sm font-medium">
<Award className="h-5 w-5 text-primary-navy" />
<span>Veteran Owned</span>
</div>
<div className="flex items-center gap-2 px-4 py-2 bg-white/20 rounded-lg text-sm font-numeric">
<span>25+</span>
<span className="text-sm">Years Experience</span>
</div>
<div className="flex items-center gap-2 px-4 py-2 bg-white/20 rounded-lg text-sm font-medium">
<span>SMB to Enterprise</span>
</div>
</div>
</div>
<div className="md:order-2 md:mt-0">
<div className="relative rounded-xl overflow-hidden shadow-2xl">
<img
src="/assets/hero-tech.webp"
alt="Business communications and IT infrastructure solutions by Queue North Technologies"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-t from-primary-navy/50 to-transparent" />
</div>
</div>
</div>
</div> </div>
</section>
{/* Trusted Partners */ } <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 md:py-24 lg:py-28">
<section className="bg-primary-navy py-16 md:py-24"> <div className="max-w-3xl">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center"> <div className="inline-flex items-center gap-2 rounded-md border border-white/20 bg-white/10 px-3 py-2 text-xs font-semibold uppercase tracking-wide text-primary-cyan">
<h2 className="text-2xl md:text-3xl font-bold text-white mb-8">Trusted Partners</h2> <span className="h-1.5 w-1.5 rounded-full bg-primary-cyan" />
<div className="flex flex-wrap justify-center items-center gap-8 md:gap-16 opacity-90"> Veteran-owned communications and infrastructure partner
<div className="flex items-center gap-3">
<img src="/assets/8x8_Logo_White.svg" alt="8x8 Certified Partner" className="h-10 w-auto" />
<span className="font-medium text-white">8x8 Certified Partner</span>
</div> </div>
<div className="flex items-center gap-3"> <h1 className="mt-6 text-4xl md:text-6xl lg:text-7xl font-bold leading-tight">
<ShieldCheck className="h-10 w-10 text-primary-cyan flex-shrink-0" /> Queue North Technologies
<span className="font-medium text-white">Cisco Certified Partner</span> </h1>
</div> <p className="mt-6 text-lg md:text-2xl text-white/80 max-w-2xl leading-relaxed">
<div className="flex items-center gap-3"> Business phone, contact center, network, and IT support built around one accountable implementation partner.
<Award className="h-10 w-10 text-primary-cyan flex-shrink-0" />
<span className="font-medium text-white">Veteran Owned</span>
</div>
</div>
</div>
</section>
{/* Trust Signals Section */}
<section className="bg-section-alt py-16 md:py-24">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-2xl md:text-3xl font-semibold text-primary-navy mb-2">Trusted by Thousands of Businesses</h2>
<p className="text-xl text-soft-text max-w-2xl mx-auto mb-6">
Why Queue North? Proven reliability, decades of experience, and unwavering support
</p> </p>
<div> <div className="mt-8 flex flex-col sm:flex-row gap-3">
<Link to="/contact" className="inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 bg-primary-navy text-white hover:bg-primary-navy-dark transition-colors" aria-label="Request a consultation"> <Link to="/contact" className="inline-flex h-11 items-center justify-center gap-2 rounded-md bg-white px-5 text-sm font-semibold text-primary-navy hover:bg-section-alt transition-colors" aria-label="Schedule a consultation">
Request Consultation Schedule Consultation
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link>
<Link to="/services" className="inline-flex h-11 items-center justify-center rounded-md border border-white/45 px-5 text-sm font-semibold text-white hover:bg-white/10 transition-colors" aria-label="View our services">
View Services
</Link> </Link>
</div> </div>
</div>
{/* 8x8 Certified Partner */} </div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12"> </section>
<div className="bg-white rounded-xl p-8 shadow-lg hover:shadow-xl transition-shadow">
<div className="flex items-center gap-4 mb-4">
<div className="bg-primary-navy text-white p-3 rounded-lg">
<img src="/assets/8x8_Logo_White.svg" alt="8x8 Certified Partner logo" className="h-8 w-auto" />
</div>
<div>
<h3 className="text-lg font-semibold text-primary-navy">8x8 Certified Partner</h3>
<p className="text-sm text-soft-text">Certification #25432</p>
</div>
</div>
<p className="text-sm text-soft-text leading-relaxed mb-4">
Queue North holds 8x8 Sales, Sales Engineer, Build, Deployment, and Support Certifications enabling full lifecycle delivery.
</p>
<div className="flex flex-wrap gap-2">
{['Sales', 'Sales Engineer', 'Build', 'Deployment', 'Support'].map((cert) => (
<span key={cert} className="inline-flex items-center gap-1.5 px-3 py-1.5 bg-teal-50 text-teal-700 text-xs font-medium rounded-md border border-teal-100">
<span className="w-1.5 h-1.5 rounded-full bg-teal-500" />
{cert}
</span>
))}
</div>
</div>
{/* Cisco Partnership */} {/* Partner Proof */}
<div className="bg-white rounded-xl p-8 shadow-lg hover:shadow-xl transition-shadow"> <section className="bg-white border-b border-border py-6">
<div className="flex items-center gap-4 mb-4"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="bg-primary-navy text-white p-3 rounded-lg"> <div className="grid grid-cols-2 gap-4 md:grid-cols-4">
<ShieldCheck className="w-6 h-6" /> <div className="flex items-center gap-3">
</div> <span className="flex h-10 w-10 items-center justify-center rounded-md bg-primary-navy">
<div> <img src="/assets/8x8_Logo_White.svg" alt="8x8 Certified Partner logo" className="h-6 w-6" />
<h3 className="text-lg font-semibold text-primary-navy">Cisco Certified Partner</h3> </span>
<p className="text-sm text-soft-text">Authorized Reseller & Implementer</p> <span className="text-sm font-semibold text-primary-navy">8x8 Certified Partner</span>
</div>
</div>
<p className="text-sm text-soft-text leading-relaxed">
As a Cisco Certified Partner, we deliver enterprise-grade solutions using Cisco Meraki, Cisco Webex, and Cisco Unified Communications Manager. We help businesses leverage Cisco's industry-leading networking and communications platforms.
</p>
</div>
{/* Veteran Owned */}
<div className="bg-white rounded-xl p-8 shadow-lg hover:shadow-xl transition-shadow">
<div className="flex items-center gap-4 mb-4">
<div className="bg-primary-navy text-white p-3 rounded-lg">
<Award className="w-6 h-6" />
</div>
<div>
<h3 className="text-lg font-semibold text-primary-navy">Veteran Owned</h3>
<p className="text-sm text-soft-text">VCERT Verified (VOSB #12847)</p>
</div>
</div>
<p className="text-sm text-soft-text leading-relaxed">
Founded by military veterans, we bring discipline, reliability, and service-first values to every client relationship. Your success is our mission.
</p>
</div>
{/* Years Experience */}
<div className="bg-white rounded-xl p-8 shadow-lg hover:shadow-xl transition-shadow">
<div className="flex items-center gap-4 mb-4">
<div className="bg-teal-600 text-white p-3 rounded-lg">
<span className="font-numeric text-3xl">25+</span>
</div>
<div>
<h3 className="text-lg font-semibold text-primary-navy">25+ Years Experience</h3>
<p className="text-sm text-soft-text">1999Present</p>
</div>
</div>
<p className="text-sm text-soft-text leading-relaxed">
We've been helping businesses navigate communications challenges since before cloud telephony existed. Our experience means fewer surprises, faster solutions.
</p>
</div>
</div> </div>
<div className="flex items-center gap-3">
{/* Metrics Grid */} <span className="flex h-10 w-10 items-center justify-center rounded-md bg-section-alt text-primary-navy">
<div className="grid grid-cols-2 md:grid-cols-4 gap-6"> <ShieldCheck className="h-5 w-5" aria-hidden="true" />
<div className="text-center"> </span>
<div className="font-numeric text-4xl md:text-5xl text-primary-navy mb-2">99.99%</div> <span className="text-sm font-semibold text-primary-navy">Cisco Certified Partner</span>
<div className="text-sm text-soft-text uppercase tracking-wide font-medium">Uptime Guarantee</div> </div>
</div> <div className="flex items-center gap-3">
<div className="text-center"> <span className="flex h-10 w-10 items-center justify-center rounded-md bg-section-alt text-primary-navy">
<div className="font-numeric text-4xl md:text-5xl text-primary-navy mb-2">&lt;15m</div> <Award className="h-5 w-5" aria-hidden="true" />
<div className="text-sm text-soft-text uppercase tracking-wide font-medium">Avg. Response</div> </span>
</div> <span className="text-sm font-semibold text-primary-navy">Veteran Owned</span>
<div className="text-center"> </div>
<div className="font-numeric text-4xl md:text-5xl text-primary-navy mb-2">24/7</div> <div className="flex items-center gap-3">
<div className="text-sm text-soft-text uppercase tracking-wide font-medium">Support</div> <span className="font-numeric flex h-10 w-10 items-center justify-center rounded-md bg-section-alt text-lg text-primary-navy">25+</span>
</div> <span className="text-sm font-semibold text-primary-navy">Years Experience</span>
<div className="text-center">
<div className="font-numeric text-4xl md:text-5xl text-primary-navy mb-2">100%</div>
<div className="text-sm text-soft-text uppercase tracking-wide font-medium">Satisfaction</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -264,10 +147,10 @@ const Home = () => {
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{services.map((service) => ( {services.map((service) => (
<Card key={service.id} className="hover:shadow-md transition-shadow cursor-pointer"> <Card key={service.id} className="h-full transition-all hover:border-primary-blue/40 hover:shadow-md">
<CardHeader> <CardHeader>
<div className="flex items-center gap-3 mb-2"> <div className="flex items-center gap-3 mb-2">
<div className="bg-primary-navy/10 p-2 rounded-lg" aria-hidden="true"> <div className="bg-primary-navy/10 p-2 rounded-md" aria-hidden="true">
{service.icon === 'message-circle' && <MessageCircle className="w-6 h-6 text-primary-navy" />} {service.icon === 'message-circle' && <MessageCircle className="w-6 h-6 text-primary-navy" />}
{service.icon === 'users' && <Users className="w-6 h-6 text-primary-navy" />} {service.icon === 'users' && <Users className="w-6 h-6 text-primary-navy" />}
{service.icon === 'life-buoy' && <LifeBuoy className="w-6 h-6 text-primary-navy" />} {service.icon === 'life-buoy' && <LifeBuoy className="w-6 h-6 text-primary-navy" />}
@ -282,11 +165,9 @@ const Home = () => {
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<Link to={`/services/${service.id}`} className="text-primary-navy p-0 h-auto text-sm hover:underline" aria-label={`Learn more about ${service.name}`}> <Link to={`/services/${service.id}`} className="inline-flex items-center gap-1 text-sm font-semibold text-primary-navy hover:text-primary-blue" aria-label={`Learn more about ${service.name}`}>
Learn more Learn more
</Link> <ArrowRight className="h-4 w-4" aria-hidden="true" />
<Link to="/contact" className="inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 border border-primary-navy text-primary-navy hover:bg-primary-navy hover:text-white transition-colors" aria-label="Learn more about services">
Request Consultation
</Link> </Link>
</div> </div>
</CardContent> </CardContent>
@ -311,9 +192,9 @@ const Home = () => {
</div> </div>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<Card> <Card className="bg-white/80">
<CardContent className="pt-6"> <CardContent className="pt-6">
<div className="bg-primary-navy text-white p-3 rounded-lg mb-4 inline-flex"> <div className="bg-primary-navy text-white p-3 rounded-md mb-4 inline-flex">
<Headphones className="w-6 h-6" /> <Headphones className="w-6 h-6" />
</div> </div>
<h3 className="text-lg font-semibold text-primary-navy mb-2">Responsiveness</h3> <h3 className="text-lg font-semibold text-primary-navy mb-2">Responsiveness</h3>
@ -322,9 +203,9 @@ const Home = () => {
</p> </p>
</CardContent> </CardContent>
</Card> </Card>
<Card> <Card className="bg-white/80">
<CardContent className="pt-6"> <CardContent className="pt-6">
<div className="bg-primary-navy text-white p-3 rounded-lg mb-4 inline-flex"> <div className="bg-primary-navy text-white p-3 rounded-md mb-4 inline-flex">
<UserCheck className="w-6 h-6" /> <UserCheck className="w-6 h-6" />
</div> </div>
<h3 className="text-lg font-semibold text-primary-navy mb-2">Direct Support</h3> <h3 className="text-lg font-semibold text-primary-navy mb-2">Direct Support</h3>
@ -333,9 +214,9 @@ const Home = () => {
</p> </p>
</CardContent> </CardContent>
</Card> </Card>
<Card> <Card className="bg-white/80">
<CardContent className="pt-6"> <CardContent className="pt-6">
<div className="bg-primary-navy text-white p-3 rounded-lg mb-4 inline-flex"> <div className="bg-primary-navy text-white p-3 rounded-md mb-4 inline-flex">
<Activity className="w-6 h-6" /> <Activity className="w-6 h-6" />
</div> </div>
<h3 className="text-lg font-semibold text-primary-navy mb-2">Proactive Monitoring</h3> <h3 className="text-lg font-semibold text-primary-navy mb-2">Proactive Monitoring</h3>
@ -344,9 +225,9 @@ const Home = () => {
</p> </p>
</CardContent> </CardContent>
</Card> </Card>
<Card> <Card className="bg-white/80">
<CardContent className="pt-6"> <CardContent className="pt-6">
<div className="bg-primary-navy text-white p-3 rounded-lg mb-4 inline-flex"> <div className="bg-primary-navy text-white p-3 rounded-md mb-4 inline-flex">
<ShieldCheck className="w-6 h-6" /> <ShieldCheck className="w-6 h-6" />
</div> </div>
<h3 className="text-lg font-semibold text-primary-navy mb-2">Vendor Neutrality</h3> <h3 className="text-lg font-semibold text-primary-navy mb-2">Vendor Neutrality</h3>
@ -372,15 +253,16 @@ const Home = () => {
{industries.map((industry) => { {industries.map((industry) => {
const IconComponent = industryIcons[industry.icon] || Building2 const IconComponent = industryIcons[industry.icon] || Building2
return ( return (
<Card key={industry.id} className="hover:shadow-md transition-shadow cursor-pointer"> <Card key={industry.id} className="h-full transition-all hover:border-primary-blue/40 hover:shadow-md">
<CardContent className="p-6"> <CardContent className="p-6">
<div className="w-14 h-14 rounded-xl bg-teal-50 flex items-center justify-center mb-4" aria-hidden="true"> <div className="w-14 h-14 rounded-md bg-teal-50 flex items-center justify-center mb-4" aria-hidden="true">
<IconComponent className="w-8 h-8 text-teal-600" /> <IconComponent className="w-8 h-8 text-teal-600" />
</div> </div>
<h3 className="text-xl font-semibold text-primary-navy mb-3" aria-label={industry.name}>{industry.name}</h3> <h3 className="text-xl font-semibold text-primary-navy mb-3" aria-label={industry.name}>{industry.name}</h3>
<p className="text-sm text-soft-text mb-4" aria-label={industry.homeDesc || 'Industry-specific solutions designed to address your unique challenges and requirements.'}>{industry.homeDesc || 'Industry-specific solutions designed to address your unique challenges and requirements.'}</p> <p className="text-sm text-soft-text mb-4" aria-label={industry.homeDesc || 'Industry-specific solutions designed to address your unique challenges and requirements.'}>{industry.homeDesc || 'Industry-specific solutions designed to address your unique challenges and requirements.'}</p>
<Link to={`/industries/${industry.id}`} className="text-primary-navy p-0 h-auto text-sm hover:underline" aria-label={`Learn more about ${industry.name} industry solutions`}> <Link to={`/industries/${industry.id}`} className="inline-flex items-center gap-1 text-sm font-semibold text-primary-navy hover:text-primary-blue" aria-label={`Learn more about ${industry.name} industry solutions`}>
Learn more Learn more
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link> </Link>
</CardContent> </CardContent>
</Card> </Card>
@ -398,7 +280,7 @@ const Home = () => {
</h2> </h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-8"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<div className="bg-primary-navy/10 p-2 rounded-lg flex-shrink-0"> <div className="bg-primary-navy/10 p-2 rounded-md flex-shrink-0">
<MapPin className="w-5 h-5 text-primary-navy" /> <MapPin className="w-5 h-5 text-primary-navy" />
</div> </div>
<p className="text-left text-sm md:text-base text-soft-text"> <p className="text-left text-sm md:text-base text-soft-text">
@ -406,7 +288,7 @@ const Home = () => {
</p> </p>
</div> </div>
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<div className="bg-teal-500/10 p-2 rounded-lg flex-shrink-0"> <div className="bg-teal-500/10 p-2 rounded-md flex-shrink-0">
<Users className="w-5 h-5 text-teal-600" /> <Users className="w-5 h-5 text-teal-600" />
</div> </div>
<p className="text-left text-sm md:text-base text-soft-text"> <p className="text-left text-sm md:text-base text-soft-text">
@ -414,7 +296,7 @@ const Home = () => {
</p> </p>
</div> </div>
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<div className="bg-teal-500/10 p-2 rounded-lg flex-shrink-0"> <div className="bg-teal-500/10 p-2 rounded-md flex-shrink-0">
<Network className="w-5 h-5 text-teal-600" /> <Network className="w-5 h-5 text-teal-600" />
</div> </div>
<p className="text-left text-sm md:text-base text-soft-text"> <p className="text-left text-sm md:text-base text-soft-text">
@ -422,7 +304,7 @@ const Home = () => {
</p> </p>
</div> </div>
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<div className="bg-teal-600/10 p-2 rounded-lg flex-shrink-0"> <div className="bg-teal-600/10 p-2 rounded-md flex-shrink-0">
<ShieldCheck className="w-5 h-5 text-teal-600" /> <ShieldCheck className="w-5 h-5 text-teal-600" />
</div> </div>
<p className="text-left text-sm md:text-base text-teal-700 font-semibold"> <p className="text-left text-sm md:text-base text-teal-700 font-semibold">

View File

@ -43,11 +43,11 @@ const Industries = () => {
{industries.map((industry) => { {industries.map((industry) => {
const IconComponent = industryIcons[industry.icon] || Building2 const IconComponent = industryIcons[industry.icon] || Building2
return ( return (
<div key={industry.id} className="group cursor-pointer"> <div key={industry.id} className="group">
<div className="rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-shadow bg-card border border-border"> <div className="rounded-md overflow-hidden shadow-sm hover:shadow-md transition-shadow bg-card border border-border">
<div className="p-6"> <div className="p-6">
<div className="flex items-center gap-4 mb-4"> <div className="flex items-center gap-4 mb-4">
<div className="h-12 w-12 rounded-lg bg-section-alt flex items-center justify-center flex-shrink-0"> <div className="h-12 w-12 rounded-md bg-section-alt flex items-center justify-center flex-shrink-0">
<IconComponent className="h-6 w-6 text-primary-navy" /> <IconComponent className="h-6 w-6 text-primary-navy" />
</div> </div>
<h2 className="text-xl font-semibold text-primary-navy group-hover:text-primary-navy-dark transition-colors"> <h2 className="text-xl font-semibold text-primary-navy group-hover:text-primary-navy-dark transition-colors">

View File

@ -3,6 +3,13 @@ import { useParams } from 'react-router-dom'
import { services } from '@/data/services' import { services } from '@/data/services'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card'
import { ArrowRight, CheckCircle2, Zap } from 'lucide-react'
const serviceImageAlt = {
'contact-center': 'Modern contact center operations dashboard and support team',
'infrastructure-cabling': 'Close-up of network cabling connected to infrastructure equipment',
'wireless-access': 'Wireless coverage planning map used for enterprise Wi-Fi design',
}
const ServiceDetail = () => { const ServiceDetail = () => {
const { slug } = useParams() const { slug } = useParams()
@ -31,6 +38,7 @@ const ServiceDetail = () => {
const serviceTitle = `${service.name} | Queue North Technologies` const serviceTitle = `${service.name} | Queue North Technologies`
const serviceDesc = service.shortDesc || `Learn about ${service.name} from Queue North Technologies.` const serviceDesc = service.shortDesc || `Learn about ${service.name} from Queue North Technologies.`
const serviceUrl = `https://queuenorth.com/services/${service.id}` const serviceUrl = `https://queuenorth.com/services/${service.id}`
const hasServiceImage = Boolean(service.image)
const serviceDetailLd = { const serviceDetailLd = {
'@context': 'https://schema.org', '@context': 'https://schema.org',
@ -62,23 +70,33 @@ const ServiceDetail = () => {
<script type="application/ld+json">{JSON.stringify(serviceDetailLd)}</script> <script type="application/ld+json">{JSON.stringify(serviceDetailLd)}</script>
</Helmet> </Helmet>
{/* Page Hero */} {/* Page Hero */}
<section className="bg-background py-16 md:py-24"> <section className="bg-background py-14 md:py-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div> <div className={hasServiceImage ? 'grid grid-cols-1 lg:grid-cols-[0.9fr_1.1fr] gap-10 lg:gap-14 items-center' : 'max-w-3xl'}>
<h1 className="text-4xl md:text-5xl font-bold text-primary-navy mb-6">{service.name}</h1> <div>
{service.image && ( <Link to="/services" className="mb-5 inline-flex text-sm font-semibold text-primary-blue hover:text-primary-navy">
<div className="relative mb-8 rounded-xl overflow-hidden"> Services
</Link>
<h1 className="text-4xl md:text-5xl font-bold text-primary-navy mb-6">{service.name}</h1>
<p className="text-xl text-soft-text max-w-3xl leading-relaxed">{service.shortDesc}</p>
<div className="mt-8">
<Link to="/contact" className="inline-flex h-11 items-center justify-center gap-2 rounded-md bg-primary-navy px-5 text-sm font-semibold text-white hover:bg-primary-navy-dark transition-colors">
Request This Service
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link>
</div>
</div>
{hasServiceImage && (
<div className="relative overflow-hidden rounded-md border border-border bg-white shadow-sm">
<img <img
src={service.image} src={service.image}
alt={service.id === 'infrastructure-cabling' ? 'Professional structured cabling installation' alt={serviceImageAlt[service.id] || `${service.name} service visual`}
: service.id === 'contact-center' ? 'Modern contact center operations with agents and dashboard' className="h-72 w-full object-cover md:h-96 lg:h-[28rem]"
: 'Network engineer with laptop configuring infrastructure'}
className="w-full h-64 md:h-80 object-cover"
/> />
<div className="absolute inset-0 bg-gradient-to-t from-primary-navy/60 to-transparent rounded-xl" /> <div className="absolute inset-x-0 bottom-0 h-24 bg-gradient-to-t from-primary-navy/55 to-transparent" />
</div> </div>
)} )}
<p className="text-xl text-soft-text max-w-3xl">{service.shortDesc}</p>
</div> </div>
</div> </div>
</section> </section>
@ -101,11 +119,7 @@ const ServiceDetail = () => {
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{service.benefits.map((benefit, index) => ( {service.benefits.map((benefit, index) => (
<div key={index} className="flex items-start gap-3"> <div key={index} className="flex items-start gap-3">
<div className="h-6 w-6 rounded-full bg-primary-navy text-white flex items-center justify-center flex-shrink-0 mt-1"> <CheckCircle2 className="h-6 w-6 text-primary-blue flex-shrink-0 mt-1" aria-hidden="true" />
<svg className="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M5 13l4 4L19 7" />
</svg>
</div>
<span className="text-lg text-text">{benefit}</span> <span className="text-lg text-text">{benefit}</span>
</div> </div>
))} ))}
@ -117,11 +131,7 @@ const ServiceDetail = () => {
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{service.idealFor.map((item, index) => ( {service.idealFor.map((item, index) => (
<div key={index} className="flex items-start gap-3"> <div key={index} className="flex items-start gap-3">
<div className="h-6 w-6 rounded-full bg-primary-navy text-white flex items-center justify-center flex-shrink-0 mt-1"> <Zap className="h-6 w-6 text-primary-blue flex-shrink-0 mt-1" aria-hidden="true" />
<svg className="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
</div>
<span className="text-lg text-text">{item}</span> <span className="text-lg text-text">{item}</span>
</div> </div>
))} ))}

View File

@ -49,11 +49,11 @@ const Services = () => {
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{services.map((service) => ( {services.map((service) => (
<div key={service.id} className="group cursor-pointer"> <div key={service.id} className="group">
<div className="rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-shadow bg-card border border-border"> <div className="rounded-md overflow-hidden shadow-sm hover:shadow-md transition-shadow bg-card border border-border">
<div className="p-6"> <div className="p-6">
<div className="flex items-center gap-4 mb-4"> <div className="flex items-center gap-4 mb-4">
<div className="h-12 w-12 rounded-lg bg-section-alt flex items-center justify-center flex-shrink-0"> <div className="h-12 w-12 rounded-md bg-section-alt flex items-center justify-center flex-shrink-0">
{service.icon === 'message-circle' && <MessageCircle className="h-6 w-6 text-primary-navy" />} {service.icon === 'message-circle' && <MessageCircle className="h-6 w-6 text-primary-navy" />}
{service.icon === 'users' && <Users className="h-6 w-6 text-primary-navy" />} {service.icon === 'users' && <Users className="h-6 w-6 text-primary-navy" />}
{service.icon === 'life-buoy' && <LifeBuoy className="h-6 w-6 text-primary-navy" />} {service.icon === 'life-buoy' && <LifeBuoy className="h-6 w-6 text-primary-navy" />}

View File

@ -5,9 +5,34 @@ import { Button } from '@/components/ui/Button'
import { Input } from '@/components/ui/Input' import { Input } from '@/components/ui/Input'
import { Textarea } from '@/components/ui/Textarea' import { Textarea } from '@/components/ui/Textarea'
import { Select } from '@/components/ui/Select' import { Select } from '@/components/ui/Select'
import { Link } from 'react-router-dom'
import { submitSupport } from '@/lib/api' import { submitSupport } from '@/lib/api'
import { useDebounce } from '@/hooks/useDebounce' import { useDebounce } from '@/hooks/useDebounce'
import { AlertCircle, ArrowRight, CheckCircle2, Clock3, ExternalLink, Headphones, LifeBuoy, ShieldCheck, TicketCheck, Wrench } from 'lucide-react'
const portalLinks = [
{
label: 'Sign in',
href: 'https://queuenorthtechnologiesllc.zohodesk.com/portal/en/signin',
},
{
label: 'Create account',
href: 'https://queuenorthtechnologiesllc.zohodesk.com/portal/en/signup',
},
]
const responseTargets = [
{ priority: 'Low', context: 'General request', target: '24 hours' },
{ priority: 'Medium', context: 'Standard issue', target: '4 hours' },
{ priority: 'High', context: 'Critical outage', target: '1 hour' },
]
const supportedSystems = [
'8x8 Communications Platform',
'VoIP Phone Systems',
'Contact Center Solutions',
'Network Infrastructure',
'Cloud Migration Support',
]
const Support = () => { const Support = () => {
const [formState, setFormState] = useState({ const [formState, setFormState] = useState({
@ -51,7 +76,7 @@ const Support = () => {
} }
// Validate issue minimum length (10 chars matches server-side Zod rule) // Validate issue minimum length (10 chars matches server-side Zod rule)
if (formState.issue.trim().length < 10) { if (formState.issue.trim() && formState.issue.trim().length < 10) {
newErrors.issue = 'Issue description must be at least 10 characters' newErrors.issue = 'Issue description must be at least 10 characters'
} }
@ -84,6 +109,7 @@ const Support = () => {
phone: '', phone: '',
issue: '', issue: '',
priority: 'medium', priority: 'medium',
company_website: '',
}) })
setErrors({ setErrors({
name: '', name: '',
@ -120,105 +146,141 @@ const Support = () => {
<meta property="og:site_name" content="Queue North Technologies" /> <meta property="og:site_name" content="Queue North Technologies" />
</Helmet> </Helmet>
{/* Page Hero */} {/* Page Hero */}
<section className="bg-background py-16 md:py-24"> <section className="bg-primary-navy py-16 lg:py-20 text-white">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div> <div className="grid grid-cols-1 lg:grid-cols-[1fr_0.72fr] gap-10 lg:gap-14 items-center">
<h1 className="text-4xl md:text-5xl font-bold text-primary-navy mb-6">Support</h1> <div>
<p className="text-xl text-soft-text max-w-3xl mb-8"> <div className="inline-flex items-center gap-2 rounded-md border border-white/20 bg-white/10 px-3 py-2 text-xs font-semibold uppercase tracking-wide text-primary-cyan">
Need help with your communications or infrastructure? Submit a support request and we'll get back to you promptly. <LifeBuoy className="h-4 w-4" aria-hidden="true" />
</p> Queue North Support
<div className="flex flex-wrap gap-4 mb-8"> </div>
<div className="flex items-center gap-2 px-4 py-2 bg-primary-navy/10 rounded-lg text-primary-navy"> <h1 className="mt-6 text-4xl md:text-5xl lg:text-6xl font-bold leading-tight">
<svg className="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> Get help without getting handed off.
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 5.13a1 1 0 01-1.31.42a2 2 0 00-2.63-.54l-2.238 5.03a2 2 0 01-2.71.319L2.663 12H4a2 2 0 012 2v2a2 2 0 01-2 2H2a2 2 0 01-2-2V5z" /> </h1>
</svg> <p className="mt-6 text-lg md:text-xl text-white/75 max-w-2xl leading-relaxed">
<p className="text-sm font-medium"><a href="tel:+13217308020" className="text-primary-cyan hover:text-cyan-700 underline" aria-label="Call (321) 730-8020">(321) 730-8020</a></p> Open a support request, access the client portal, or escalate a service-impacting issue through one clear path.
</p>
<div className="mt-8 flex flex-col sm:flex-row gap-3">
<a href="#support-request" className="inline-flex h-11 items-center justify-center gap-2 rounded-md bg-white px-5 text-sm font-semibold text-primary-navy hover:bg-section-alt transition-colors">
Submit Request
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</a>
<a
href={portalLinks[0].href}
target="_blank"
rel="noopener noreferrer"
className="inline-flex h-11 items-center justify-center gap-2 rounded-md border border-white/40 px-5 text-sm font-semibold text-white hover:bg-white/10 transition-colors"
>
Open Portal
<ExternalLink className="h-4 w-4" aria-hidden="true" />
</a>
</div> </div>
</div> </div>
<div className="mb-8">
<Link to="/contact" className="inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-6 bg-primary-navy text-white hover:bg-primary-navy-dark transition-colors"> <div className="rounded-md border border-white/15 bg-white/10 p-6 shadow-xl backdrop-blur">
Request Consultation <h2 className="text-lg font-semibold mb-5">Choose the right path</h2>
</Link> <div className="space-y-4">
<div className="flex gap-4">
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-md bg-white/10 text-primary-cyan">
<TicketCheck className="h-5 w-5" aria-hidden="true" />
</span>
<div>
<h3 className="font-semibold">Existing client</h3>
<p className="text-sm text-white/70">Submit the form or use the portal to track requests.</p>
</div>
</div>
<div className="flex gap-4">
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-md bg-white/10 text-primary-cyan">
<AlertCircle className="h-5 w-5" aria-hidden="true" />
</span>
<div>
<h3 className="font-semibold">Active outage</h3>
<a href="tel:+13217308020" className="text-sm font-semibold text-primary-cyan hover:text-white transition-colors" aria-label="Call Queue North support">
Call (321) 730-8020
</a>
</div>
</div>
<div className="flex gap-4">
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-md bg-white/10 text-primary-cyan">
<Wrench className="h-5 w-5" aria-hidden="true" />
</span>
<div>
<h3 className="font-semibold">Planned work</h3>
<p className="text-sm text-white/70">Use the request form for moves, adds, changes, and deployments.</p>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
{/* Support Form */} {/* Support Form */}
<section className="bg-background py-16"> <section id="support-request" className="bg-background py-16 lg:py-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12"> <div className="grid grid-cols-1 lg:grid-cols-[0.9fr_1.1fr] gap-8 lg:gap-10 items-start">
{/* Left - Info */} {/* Left - Info */}
<div> <div className="space-y-6">
<div className="mb-8"> <div className="rounded-md border border-border bg-white p-6 shadow-sm">
<h2 className="text-2xl font-bold text-primary-navy mb-4">Support Services</h2> <div className="flex items-start gap-4">
<p className="text-soft-text mb-6"> <span className="flex h-11 w-11 shrink-0 items-center justify-center rounded-md bg-primary-navy text-white">
We provide comprehensive support for all our services, including 24/7 monitoring, rapid response, and dedicated support engineers. <Headphones className="h-5 w-5" aria-hidden="true" />
</p> </span>
<div className="space-y-4">
<div className="bg-section-alt rounded-lg p-6">
<h3 className="font-semibold text-primary-navy mb-4">Queue North Support Center</h3>
<p className="text-text mb-6">
Need to sign up for the Queue North Support Center? Create an account to access our knowledge base and submit support tickets.
</p>
<div className="flex flex-wrap gap-4 mb-4">
<a
href="https://queuenorthtechnologiesllc.zohodesk.com/portal/en/signup"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center justify-center px-6 py-3 bg-primary-navy text-white font-medium rounded-md hover:bg-primary-navy-dark transition-colors"
>
Sign Up
<svg className="ml-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
</a>
<a
href="https://queuenorthtechnologiesllc.zohodesk.com/portal/en/signin"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center justify-center px-6 py-3 bg-white text-primary-navy font-medium rounded-md hover:bg-gray-50 transition-colors"
>
Already a member? Sign In
</a>
</div>
<p className="text-sm text-soft-text">
Or call our support team <a href="tel:+13217308020" className="text-primary-cyan hover:text-cyan-700 underline" aria-label="Call (321) 730-8020">(321) 730-8020</a>
</p>
</div>
<div> <div>
<h3 className="font-semibold text-text mb-2">Phone</h3> <h2 className="text-xl font-bold text-primary-navy">Support Center</h2>
<p className="text-soft-text"><a href="tel:+13217308020" className="text-primary-cyan hover:text-cyan-700 underline" aria-label="Call (321) 730-8020">(321) 730-8020</a></p> <p className="mt-2 text-sm leading-relaxed text-soft-text">
</div> Sign in to manage existing tickets, create an account, or submit the form on this page for a new request.
<div>
<h3 className="font-semibold text-text mb-2">Support Hours</h3>
<p className="text-soft-text">24/7 Monitoring with rapid response SLAs</p>
</div>
<div>
<h3 className="font-semibold text-text mb-2">Priority Levels</h3>
<p className="text-soft-text">
Low: General inquiries (response within 24 hours)<br/>
Medium: Standard issues (response within 4 hours)<br/>
High: Critical issues (response within 1 hour)
</p> </p>
</div> </div>
</div> </div>
<div className="mt-6 flex flex-col sm:flex-row gap-3">
{portalLinks.map((link, index) => (
<a
key={link.label}
href={link.href}
target="_blank"
rel="noopener noreferrer"
className={`inline-flex h-10 items-center justify-center gap-2 rounded-md px-4 text-sm font-semibold transition-colors ${index === 0 ? 'bg-primary-navy text-white hover:bg-primary-navy-dark' : 'border border-border bg-white text-primary-navy hover:bg-section-alt'}`}
>
{link.label}
<ExternalLink className="h-4 w-4" aria-hidden="true" />
</a>
))}
</div>
</div> </div>
<div className="bg-section-alt rounded-lg p-6"> <div className="rounded-md border border-border bg-white p-6 shadow-sm">
<h3 className="font-semibold text-primary-navy mb-4">What We Support</h3> <div className="flex items-center gap-3 mb-5">
<span className="flex h-10 w-10 items-center justify-center rounded-md bg-section-alt text-primary-navy">
<Clock3 className="h-5 w-5" aria-hidden="true" />
</span>
<h2 className="text-xl font-bold text-primary-navy">Response Targets</h2>
</div>
<div className="grid gap-3 sm:grid-cols-3 lg:grid-cols-1">
{responseTargets.map((item) => (
<div key={item.priority} className="rounded-md border border-border bg-background p-4">
<div className="flex items-center justify-between gap-3">
<p className="font-semibold text-text">{item.priority}</p>
<p className="font-numeric text-xl text-primary-navy">{item.target}</p>
</div>
<p className="mt-1 text-sm text-soft-text">{item.context}</p>
</div>
))}
</div>
</div>
<div className="rounded-md border border-border bg-section-alt p-6">
<div className="flex items-center gap-3 mb-5">
<span className="flex h-10 w-10 items-center justify-center rounded-md bg-white text-primary-navy">
<ShieldCheck className="h-5 w-5" aria-hidden="true" />
</span>
<h2 className="text-xl font-bold text-primary-navy">Covered Systems</h2>
</div>
<ul className="space-y-3"> <ul className="space-y-3">
{[ {supportedSystems.map((item) => (
'8x8 Communications Platform', <li key={item} className="flex items-center gap-3 text-sm text-text">
'VoIP Phone Systems', <CheckCircle2 className="h-5 w-5 shrink-0 text-primary-blue" aria-hidden="true" />
'Contact Center Solutions',
'Network Infrastructure',
'Cloud Migration Support',
].map((item, index) => (
<li key={index} className="flex items-center gap-3 text-text">
<svg className="h-5 w-5 text-primary-navy" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M5 13l4 4L19 7" />
</svg>
{item} {item}
</li> </li>
))} ))}
@ -228,76 +290,87 @@ const Support = () => {
{/* Right - Form */} {/* Right - Form */}
<div> <div>
<form onSubmit={handleSubmit} noValidate className={`space-y-6 ${isSubmitting ? 'opacity-70 pointer-events-none' : ''}`}> <form onSubmit={handleSubmit} noValidate className={`rounded-md border border-border bg-white p-6 shadow-sm lg:p-8 space-y-5 ${isSubmitting ? 'opacity-70 pointer-events-none' : ''}`}>
<div> <div className="border-b border-border pb-5">
<label htmlFor="name" className="block text-sm font-medium text-text mb-2"> <h2 className="text-2xl font-bold text-primary-navy">Submit a Request</h2>
Name <span className="text-red-600">*</span> <p className="mt-2 text-sm text-soft-text">
</label> Include who is affected, what changed, and how urgent the issue is.
<Input </p>
type="text"
id="name"
name="name"
value={formState.name}
onChange={handleChange}
required
placeholder="Your full name"
className={errors.name ? 'border-red-500 focus-visible:ring-red-500' : ''}
/>
{debouncedErrors.name && (
<p className="text-xs text-red-600 mt-1">{debouncedErrors.name}</p>
)}
</div> </div>
<div> <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<label htmlFor="company" className="block text-sm font-medium text-text mb-2"> <div>
Company Name <span className="text-red-600">*</span> <label htmlFor="name" className="block text-sm font-medium text-text mb-2">
</label> Name <span className="text-red-600">*</span>
<Input </label>
type="text" <Input
id="company" type="text"
name="company" id="name"
value={formState.company} name="name"
onChange={handleChange} value={formState.name}
required onChange={handleChange}
placeholder="Your company name" required
className={errors.company ? 'border-red-500 focus-visible:ring-red-500' : ''} placeholder="Your full name"
/> className={errors.name ? 'border-red-500 focus-visible:ring-red-500' : ''}
{debouncedErrors.company && ( />
<p className="text-xs text-red-600 mt-1">{debouncedErrors.company}</p> {debouncedErrors.name && (
)} <p className="text-xs text-red-600 mt-1">{debouncedErrors.name}</p>
)}
</div>
<div>
<label htmlFor="company" className="block text-sm font-medium text-text mb-2">
Company <span className="text-red-600">*</span>
</label>
<Input
type="text"
id="company"
name="company"
value={formState.company}
onChange={handleChange}
required
placeholder="Company name"
className={errors.company ? 'border-red-500 focus-visible:ring-red-500' : ''}
/>
{debouncedErrors.company && (
<p className="text-xs text-red-600 mt-1">{debouncedErrors.company}</p>
)}
</div>
</div> </div>
<div> <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<label htmlFor="email" className="block text-sm font-medium text-text mb-2"> <div>
Email <span className="text-red-600">*</span> <label htmlFor="email" className="block text-sm font-medium text-text mb-2">
</label> Email <span className="text-red-600">*</span>
<Input </label>
type="email" <Input
id="email" type="email"
name="email" id="email"
value={formState.email} name="email"
onChange={handleChange} value={formState.email}
required onChange={handleChange}
placeholder="your.email@example.com" required
className={errors.email ? 'border-red-500 focus-visible:ring-red-500' : ''} placeholder="you@example.com"
/> className={errors.email ? 'border-red-500 focus-visible:ring-red-500' : ''}
{debouncedErrors.email && ( />
<p className="text-xs text-red-600 mt-1">{debouncedErrors.email}</p> {debouncedErrors.email && (
)} <p className="text-xs text-red-600 mt-1">{debouncedErrors.email}</p>
</div> )}
</div>
<div> <div>
<label htmlFor="phone" className="block text-sm font-medium text-text mb-2"> <label htmlFor="phone" className="block text-sm font-medium text-text mb-2">
Phone (Optional) Phone <span className="text-soft-text">(optional)</span>
</label> </label>
<Input <Input
type="tel" type="tel"
id="phone" id="phone"
name="phone" name="phone"
value={formState.phone} value={formState.phone}
onChange={handleChange} onChange={handleChange}
placeholder="(555) 123-4567" placeholder="(555) 123-4567"
/> />
</div>
</div> </div>
<div> <div>
@ -318,7 +391,7 @@ const Support = () => {
<div> <div>
<label htmlFor="issue" className="block text-sm font-medium text-text mb-2"> <label htmlFor="issue" className="block text-sm font-medium text-text mb-2">
Describe Your Issue <span className="text-red-600">*</span> Issue Details <span className="text-red-600">*</span>
</label> </label>
<Textarea <Textarea
id="issue" id="issue"
@ -326,7 +399,7 @@ const Support = () => {
value={formState.issue} value={formState.issue}
onChange={handleChange} onChange={handleChange}
required required
placeholder="Please describe your issue in detail..." placeholder="What changed, who is affected, and what have you already tried?"
className={`w-full rounded-md border bg-background px-3 py-2 text-sm ring-offset-[#F8FAFC] placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-navy focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 ${errors.issue ? 'border-red-500 focus-visible:ring-red-500' : ''}`} className={`w-full rounded-md border bg-background px-3 py-2 text-sm ring-offset-[#F8FAFC] placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-navy focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 ${errors.issue ? 'border-red-500 focus-visible:ring-red-500' : ''}`}
rows={5} rows={5}
/> />
@ -348,7 +421,7 @@ const Support = () => {
<Button <Button
type="submit" type="submit"
className="w-full" className="w-full gap-2"
disabled={isSubmitting} disabled={isSubmitting}
> >
{isSubmitting ? ( {isSubmitting ? (
@ -360,7 +433,10 @@ const Support = () => {
Submitting... Submitting...
</> </>
) : ( ) : (
'Submit Request' <>
Submit Request
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</>
)} )}
</Button> </Button>
</form> </form>