437 lines
17 KiB
TypeScript
437 lines
17 KiB
TypeScript
"use client";
|
|
import Link from "next/link";
|
|
import { useState, useEffect, useMemo } from "react";
|
|
import { useHomeBanners } from "@/lib/hooks/useHome";
|
|
|
|
const HomeBanner = () => {
|
|
const [currentTextIndex, setCurrentTextIndex] = useState(0);
|
|
const [isTransitioning, setIsTransitioning] = useState(false);
|
|
const { data: banners, loading, error } = useHomeBanners();
|
|
|
|
// Fix viewport height for mobile browsers (especially iOS Safari)
|
|
useEffect(() => {
|
|
const setVH = () => {
|
|
const vh = window.innerHeight * 0.01;
|
|
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
|
};
|
|
|
|
setVH();
|
|
window.addEventListener('resize', setVH);
|
|
// Use 'resize' event instead of deprecated 'orientationchange'
|
|
// The resize event fires on orientation change as well
|
|
const handleOrientationChange = () => {
|
|
// Small delay to ensure viewport has updated
|
|
setTimeout(setVH, 100);
|
|
};
|
|
window.addEventListener('resize', handleOrientationChange);
|
|
|
|
return () => {
|
|
window.removeEventListener('resize', setVH);
|
|
window.removeEventListener('resize', handleOrientationChange);
|
|
};
|
|
}, []);
|
|
|
|
// Transform API data to match component format
|
|
const carouselTexts = useMemo(() => {
|
|
if (!banners || banners.length === 0) return [];
|
|
|
|
return banners.map(banner => ({
|
|
icon: banner.icon,
|
|
badge: banner.badge,
|
|
heading: banner.heading,
|
|
highlight: banner.highlight,
|
|
subheading: banner.subheading,
|
|
description: banner.description,
|
|
button_text: banner.button_text,
|
|
button_url: banner.button_url,
|
|
}));
|
|
}, [banners]);
|
|
|
|
// Carousel rotation effect
|
|
useEffect(() => {
|
|
if (carouselTexts.length <= 1) return;
|
|
|
|
const interval = setInterval(() => {
|
|
setIsTransitioning(true);
|
|
|
|
setTimeout(() => {
|
|
setCurrentTextIndex((prevIndex) =>
|
|
prevIndex === carouselTexts.length - 1 ? 0 : prevIndex + 1
|
|
);
|
|
setIsTransitioning(false);
|
|
}, 1000); // Slightly longer for smoother transition
|
|
}, 6000); // Increased interval for slower changes
|
|
|
|
return () => clearInterval(interval);
|
|
}, [carouselTexts.length]);
|
|
|
|
const currentText = carouselTexts[currentTextIndex];
|
|
|
|
// Show loading state
|
|
if (loading) {
|
|
return (
|
|
<section className="modern-banner">
|
|
<div className="container">
|
|
<div className="banner-content">
|
|
<div className="content-center">
|
|
<div className="spinner-border text-primary" role="status">
|
|
<span className="visually-hidden">Loading...</span>
|
|
</div>
|
|
<p className="mt-3">Loading banner content...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
// Show error state
|
|
if (error) {
|
|
return (
|
|
<section className="modern-banner">
|
|
<div className="container">
|
|
<div className="banner-content">
|
|
<div className="content-center">
|
|
<div className="alert alert-danger" role="alert">
|
|
<h4 className="alert-heading">Error Loading Content</h4>
|
|
<p>{error}</p>
|
|
<hr />
|
|
<p className="mb-0">Please try refreshing the page or contact support if the problem persists.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
// Show no data message when there's no banner content
|
|
if (!currentText || carouselTexts.length === 0) {
|
|
return (
|
|
<section className="modern-banner">
|
|
<div className="container">
|
|
<div className="banner-content">
|
|
<div className="content-center">
|
|
<h1 className="main-heading">No data available</h1>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<section className="modern-banner">
|
|
<div className="banner-background">
|
|
<div className="gradient-orb orb-1"></div>
|
|
<div className="gradient-orb orb-2"></div>
|
|
<div className="gradient-orb orb-3"></div>
|
|
|
|
{/* Industrial Enterprise Background Elements */}
|
|
<div className="enterprise-bg-elements">
|
|
{/* Flying Code Elements */}
|
|
<div className="flying-code">
|
|
<div className="code-snippet code-1">
|
|
<span className="code-line">const enterprise = {'{'}</span>
|
|
<span className="code-line"> security: 'enterprise-grade',</span>
|
|
<span className="code-line"> scalability: 'unlimited'</span>
|
|
<span className="code-line">{'}'};</span>
|
|
</div>
|
|
<div className="code-snippet code-2">
|
|
<span className="code-line">if (security === 'max') {'{'}</span>
|
|
<span className="code-line"> deploy.enterprise();</span>
|
|
<span className="code-line">{'}'}</span>
|
|
</div>
|
|
<div className="code-snippet code-3">
|
|
<span className="code-line">class EnterpriseSoftware {'{'}</span>
|
|
<span className="code-line"> constructor() {'{'}</span>
|
|
<span className="code-line"> this.secure = true;</span>
|
|
<span className="code-line"> {'}'}</span>
|
|
<span className="code-line">{'}'}</span>
|
|
</div>
|
|
<div className="code-snippet code-4">
|
|
<span className="code-line">API.authenticate({'{'}</span>
|
|
<span className="code-line"> level: 'enterprise',</span>
|
|
<span className="code-line"> encryption: 'AES-256'</span>
|
|
<span className="code-line">{'}'});</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Industrial Grid */}
|
|
<div className="industrial-grid">
|
|
<div className="grid-line horizontal h-1"></div>
|
|
<div className="grid-line horizontal h-2"></div>
|
|
<div className="grid-line horizontal h-3"></div>
|
|
<div className="grid-line horizontal h-4"></div>
|
|
<div className="grid-line vertical v-1"></div>
|
|
<div className="grid-line vertical v-2"></div>
|
|
<div className="grid-line vertical v-3"></div>
|
|
<div className="grid-line vertical v-4"></div>
|
|
</div>
|
|
|
|
{/* Security Elements */}
|
|
<div className="security-elements">
|
|
<div className="shield shield-1">
|
|
<i className="fa-solid fa-shield-halved"></i>
|
|
</div>
|
|
<div className="shield shield-2">
|
|
<i className="fa-solid fa-lock"></i>
|
|
</div>
|
|
<div className="shield shield-3">
|
|
<i className="fa-solid fa-key"></i>
|
|
</div>
|
|
<div className="shield shield-4">
|
|
<i className="fa-solid fa-fingerprint"></i>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Circuit Patterns */}
|
|
<div className="circuit-patterns">
|
|
<div className="circuit circuit-1">
|
|
<div className="circuit-node"></div>
|
|
<div className="circuit-line"></div>
|
|
<div className="circuit-node"></div>
|
|
</div>
|
|
<div className="circuit circuit-2">
|
|
<div className="circuit-node"></div>
|
|
<div className="circuit-line"></div>
|
|
<div className="circuit-node"></div>
|
|
<div className="circuit-line"></div>
|
|
<div className="circuit-node"></div>
|
|
</div>
|
|
<div className="circuit circuit-3">
|
|
<div className="circuit-node"></div>
|
|
<div className="circuit-line"></div>
|
|
<div className="circuit-node"></div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Data Streams */}
|
|
<div className="data-streams">
|
|
<div className="stream stream-1">
|
|
<div className="data-bit"></div>
|
|
<div className="data-bit"></div>
|
|
<div className="data-bit"></div>
|
|
<div className="data-bit"></div>
|
|
</div>
|
|
<div className="stream stream-2">
|
|
<div className="data-bit"></div>
|
|
<div className="data-bit"></div>
|
|
<div className="data-bit"></div>
|
|
<div className="data-bit"></div>
|
|
<div className="data-bit"></div>
|
|
</div>
|
|
<div className="stream stream-3">
|
|
<div className="data-bit"></div>
|
|
<div className="data-bit"></div>
|
|
<div className="data-bit"></div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Request/Response Data */}
|
|
<div className="request-response-data">
|
|
<div className="api-request req-1">
|
|
<div className="request-label">POST /api/enterprise</div>
|
|
<div className="request-data">
|
|
<div className="data-packet"></div>
|
|
<div className="data-packet"></div>
|
|
<div className="data-packet"></div>
|
|
</div>
|
|
</div>
|
|
<div className="api-response resp-1">
|
|
<div className="response-label">200 OK</div>
|
|
<div className="response-data">
|
|
<div className="data-packet"></div>
|
|
<div className="data-packet"></div>
|
|
<div className="data-packet"></div>
|
|
<div className="data-packet"></div>
|
|
</div>
|
|
</div>
|
|
<div className="api-request req-2">
|
|
<div className="request-label">GET /api/analytics</div>
|
|
<div className="request-data">
|
|
<div className="data-packet"></div>
|
|
<div className="data-packet"></div>
|
|
</div>
|
|
</div>
|
|
<div className="api-response resp-2">
|
|
<div className="response-label">201 Created</div>
|
|
<div className="response-data">
|
|
<div className="data-packet"></div>
|
|
<div className="data-packet"></div>
|
|
<div className="data-packet"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Space Data Generation */}
|
|
<div className="space-data-generation">
|
|
<div className="data-cluster cluster-1">
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
</div>
|
|
<div className="data-cluster cluster-2">
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
</div>
|
|
<div className="data-cluster cluster-3">
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
</div>
|
|
<div className="data-cluster cluster-4">
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
<div className="data-point"></div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Database Connections */}
|
|
<div className="database-connections">
|
|
<div className="db-connection conn-1">
|
|
<div className="connection-line"></div>
|
|
<div className="db-node">
|
|
<i className="fa-solid fa-database"></i>
|
|
</div>
|
|
<div className="connection-pulse"></div>
|
|
</div>
|
|
<div className="db-connection conn-2">
|
|
<div className="connection-line"></div>
|
|
<div className="db-node">
|
|
<i className="fa-solid fa-server"></i>
|
|
</div>
|
|
<div className="connection-pulse"></div>
|
|
</div>
|
|
<div className="db-connection conn-3">
|
|
<div className="connection-line"></div>
|
|
<div className="db-node">
|
|
<i className="fa-solid fa-cloud"></i>
|
|
</div>
|
|
<div className="connection-pulse"></div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Real-time Metrics */}
|
|
<div className="real-time-metrics">
|
|
<div className="metric metric-1">
|
|
<div className="metric-label">API Calls/sec</div>
|
|
<div className="metric-value">2,847</div>
|
|
<div className="metric-bar">
|
|
<div className="bar-fill"></div>
|
|
</div>
|
|
</div>
|
|
<div className="metric metric-2">
|
|
<div className="metric-label">Data Processed</div>
|
|
<div className="metric-value">15.2TB</div>
|
|
<div className="metric-bar">
|
|
<div className="bar-fill"></div>
|
|
</div>
|
|
</div>
|
|
<div className="metric metric-3">
|
|
<div className="metric-label">Active Users</div>
|
|
<div className="metric-value">45,892</div>
|
|
<div className="metric-bar">
|
|
<div className="bar-fill"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="container">
|
|
<div className="banner-content">
|
|
<div className="content-center">
|
|
<div className="badge-container">
|
|
<span className="badge">
|
|
<i className={currentText.icon}></i>
|
|
{currentText.badge}
|
|
</span>
|
|
</div>
|
|
|
|
<h1 className={`main-heading carousel-text ${isTransitioning ? 'fade-out' : 'fade-in'}`}>
|
|
{currentText.heading}
|
|
<span className="gradient-text"> {currentText.highlight}</span>
|
|
<br />
|
|
{currentText.subheading}
|
|
</h1>
|
|
|
|
<p className={`description carousel-text ${isTransitioning ? 'fade-out' : 'fade-in'}`}>
|
|
{currentText.description}
|
|
</p>
|
|
|
|
{/* Carousel Indicators */}
|
|
<div className="carousel-indicators">
|
|
{carouselTexts.map((_, index) => (
|
|
<button
|
|
key={index}
|
|
className={`indicator ${index === currentTextIndex ? 'active' : ''}`}
|
|
onClick={() => {
|
|
if (index !== currentTextIndex) {
|
|
setIsTransitioning(true);
|
|
setTimeout(() => {
|
|
setCurrentTextIndex(index);
|
|
setIsTransitioning(false);
|
|
}, 1000);
|
|
}
|
|
}}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
<div className="cta-section">
|
|
<Link href={currentText.button_url || "#"} className="cta-primary">
|
|
<span>{currentText.button_text || "Learn More"}</span>
|
|
<i className="fa-solid fa-arrow-right"></i>
|
|
</Link>
|
|
<Link href="/contact-us" className="cta-secondary">
|
|
<i className="fa-solid fa-phone"></i>
|
|
<span>Contact Sales</span>
|
|
</Link>
|
|
</div>
|
|
|
|
<div className="trust-indicators">
|
|
<div className="trust-item">
|
|
<div className="trust-number">30+</div>
|
|
<div className="trust-label">Enterprise Clients</div>
|
|
</div>
|
|
<div className="trust-item">
|
|
<div className="trust-number">99.9%</div>
|
|
<div className="trust-label">Uptime SLA</div>
|
|
</div>
|
|
<div className="trust-item">
|
|
<div className="trust-number">24/7</div>
|
|
<div className="trust-label">Enterprise Support</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
<div className="scroll-indicator" onClick={() => window.scrollTo({ top: window.innerHeight, behavior: 'smooth' })}>
|
|
<div className="scroll-text">Scroll to explore</div>
|
|
<div className="scroll-arrow">
|
|
<i className="fa-solid fa-chevron-down"></i>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default HomeBanner;
|