Files
doormile_react/src/components/sections/EVLogisticSection.tsx
2026-06-15 18:20:48 +05:30

481 lines
16 KiB
TypeScript

"use client";
import React, { useEffect, useRef } from "react";
import Image from "next/image";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
if (typeof window !== "undefined") {
gsap.registerPlugin(ScrollTrigger);
}
const CARDS_DATA = [
{
index: 1,
title: "Operational Visibility",
desc: "Real-time tracking and centralized control provide complete visibility across every shipment, vehicle, and delivery milestone.",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<rect x="2" y="7" width="16" height="10" rx="2" ry="2" />
<line x1="22" y1="11" x2="22" y2="13" />
<line x1="6" y1="11" x2="10" y2="11" />
<line x1="6" y1="13" x2="12" y2="13" />
</svg>
)
},
{
index: 2,
title: "Intelligent Routing",
desc: "AI-powered route optimization reduces travel time, improves delivery accuracy, and maximizes fleet utilization.",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
</svg>
)
},
{
index: 3,
title: "EV-First Logistics",
desc: "Purpose-built workflows for electric fleets improve battery efficiency, charging management, and sustainable operations.",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M12 2v10" />
<path d="M18 8V6a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v2a4 4 0 0 0 4 4h4a4 4 0 0 0 4-4Z" />
<path d="M10 22v-6" />
<path d="M14 22v-6" />
</svg>
)
},
{
index: 4,
title: "Scalable Network",
desc: "Flexible logistics infrastructure supports growth across cities, regions, and high-volume delivery operations without disruption.",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 3.5 2 5.5a7 7 0 0 1-7 7h-3" />
<path d="M12 22V12" />
</svg>
)
}
];
export default function EVLogisticSection() {
const containerRef = useRef<HTMLDivElement>(null);
const imageWrapperRef = useRef<HTMLDivElement>(null);
const imageRef = useRef<HTMLImageElement>(null);
useEffect(() => {
const container = containerRef.current;
const img = imageRef.current;
const imgWrapper = imageWrapperRef.current;
if (!container || !img || !imgWrapper) return;
// 1. Parent Wrapper Loop: Slow Looping float
const floatAnim = gsap.to(imgWrapper, {
y: "-=10",
duration: 4.5,
ease: "sine.inOut",
yoyo: true,
repeat: -1,
});
// 2. Premium Entrance Animation on Scroll (ScrollTrigger based)
const entryTl = gsap.timeline({
scrollTrigger: {
trigger: container,
start: "top 80%",
toggleActions: "play none none none",
}
});
entryTl
.to(container.querySelector(".ev-logistic-kicker-widget"), {
opacity: 1,
y: 0,
duration: 0.8,
ease: "power3.out",
})
.to(container.querySelector(".ev-logistic-title-widget"), {
y: 0,
opacity: 1,
duration: 0.85,
ease: "power4.out",
}, "-=0.45")
.to(container.querySelectorAll(".ev-feature-card"), {
opacity: 1,
y: 0,
duration: 0.6,
stagger: 0.08,
ease: "power3.out",
}, "-=0.6")
.fromTo(img, {
opacity: 0,
scale: 0.95,
}, {
opacity: 1,
scale: 1,
duration: 1.0,
ease: "power4.out",
}, "-=0.8");
return () => {
floatAnim.kill();
};
}, []);
return (
<>
<style dangerouslySetInnerHTML={{ __html: `
/* Custom CSS Scoped to EV Logistics Section */
.ev-logistic-section {
box-sizing: border-box !important;
background: #ffffff !important;
font-family: 'Manrope', sans-serif !important;
position: relative !important;
}
.ev-logistic-header {
width: 100% !important;
max-width: 100% !important;
align-self: stretch !important;
margin-bottom: 48px !important;
display: block !important;
text-align: left !important;
}
.ev-logistic-body-grid {
display: flex !important;
flex-direction: row !important;
align-items: center !important;
justify-content: space-between !important;
width: 100% !important;
gap: 3% !important;
}
/* Left Column - Image column takes up 45% */
.ev-logistic-image-col {
flex: 0 0 45% !important;
max-width: 45% !important;
display: flex !important;
align-items: center !important;
justify-content: flex-start !important;
position: relative !important;
min-height: auto !important;
margin: 0 !important;
}
/* Branded glow spotlight halo behind the vehicle */
.ev-logistic-image-glow {
position: absolute !important;
left: 50% !important;
top: 50% !important;
width: 80% !important;
height: 70% !important;
transform: translate(-50%, -50%) !important;
background: radial-gradient(circle, rgba(192, 18, 39, 0.05) 0%, rgba(192, 18, 39, 0.01) 55%, transparent 75%) !important;
filter: blur(54px) !important;
z-index: 0 !important;
pointer-events: none !important;
}
/* Image wrapper scaling naturally inside its column container */
.ev-logistic-image-wrapper {
width: 100% !important;
max-width: 100% !important;
display: flex !important;
align-items: center !important;
justify-content: flex-start !important;
overflow: visible !important;
position: relative !important;
transform: scale(1.15) !important;
transform-origin: left center !important;
margin-left: -80px !important;
}
.ev-logistic-image-wrapper img {
width: 100% !important;
height: auto !important;
object-fit: contain !important;
filter: none !important;
will-change: transform !important;
}
/* Right column - takes up 52% for grid cards */
.ev-logistic-content-col {
flex: 0 0 52% !important;
max-width: 52% !important;
display: flex !important;
flex-direction: column !important;
justify-content: center !important;
margin: 0 !important;
}
.ev-logistic-kicker-widget {
opacity: 0;
transform: translateY(-12px);
will-change: transform, opacity;
}
.ev-logistic-title-wrapper {
margin: 0 !important;
}
.ev-logistic-title-widget {
opacity: 0;
transform: translateY(24px);
will-change: transform, opacity;
}
.ev-logistic-title-widget > .elementor-widget-container {
margin: 0 !important;
padding: 0 !important;
}
.ev-logistic-title-widget .logico-title {
margin: 0 !important;
text-align: left !important;
}
/* Card Grid Layout */
.ev-feature-grid {
display: grid !important;
grid-template-columns: repeat(2, 1fr) !important;
gap: 24px !important;
width: 100% !important;
}
/* Premium Theme White Card */
.ev-feature-card {
display: flex !important;
flex-direction: column !important;
background: #ffffff !important;
border: 1px solid rgba(17, 17, 17, 0.09) !important;
border-radius: 20px !important;
padding: 30px !important;
color: #555555 !important;
height: 100% !important;
box-sizing: border-box !important;
opacity: 0;
transform: translateY(20px);
will-change: transform, opacity;
transition: border-color 0.4s cubic-bezier(0.165, 0.84, 0.44, 1),
box-shadow 0.4s cubic-bezier(0.165, 0.84, 0.44, 1),
transform 0.4s cubic-bezier(0.165, 0.84, 0.44, 1) !important;
box-shadow: 0 4px 24px rgba(17, 17, 17, 0.02) !important;
}
.ev-feature-card:hover {
border-color: #c01227 !important;
box-shadow: 0 20px 40px rgba(192, 18, 39, 0.08), 0 4px 12px rgba(17, 17, 17, 0.03) !important;
transform: translateY(-8px) !important;
}
/* Red Icon Wrapper */
.ev-feature-icon-wrapper {
margin-bottom: 24px !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
width: 54px !important;
height: 54px !important;
background: rgba(192, 18, 39, 0.06) !important;
border: 1px solid rgba(192, 18, 39, 0.18) !important;
border-radius: 50% !important;
color: #c01227 !important;
transition: all 0.3s ease !important;
}
.ev-feature-card:hover .ev-feature-icon-wrapper {
background: rgba(192, 18, 39, 0.12) !important;
border-color: #c01227 !important;
transform: scale(1.1) !important;
box-shadow: 0 0 12px rgba(192, 18, 39, 0.15) !important;
}
.ev-feature-icon-wrapper svg {
width: 24px !important;
height: 24px !important;
stroke: currentColor !important;
}
/* Title & Description Inside Cards */
.ev-feature-card-title {
font-family: 'Manrope', sans-serif !important;
font-size: 20px !important;
font-weight: 700 !important;
line-height: 1.3em !important;
color: #c01227 !important;
margin: 0 0 12px 0 !important;
text-transform: none !important;
}
.ev-feature-card-desc {
font-family: 'Manrope', sans-serif !important;
font-size: 14px !important;
font-weight: 500 !important;
line-height: 1.6 !important;
color: #555555 !important;
margin: 0 !important;
}
/* Responsiveness constraints */
@media (max-width: 1024px) {
.ev-logistic-body-grid {
flex-direction: column !important;
gap: 50px !important;
}
.ev-logistic-image-col {
flex: 1 1 100% !important;
max-width: 100% !important;
min-height: auto !important;
justify-content: center !important;
}
.ev-logistic-image-wrapper {
max-width: 580px !important;
transform: none !important;
margin-left: 0 !important;
justify-content: center !important;
}
.ev-logistic-content-col {
flex: 1 1 100% !important;
max-width: 100% !important;
}
}
@media (max-width: 767px) {
.ev-logistic-section {
--padding-left: 10px !important;
--padding-right: 10px !important;
padding-left: 10px !important;
padding-right: 10px !important;
box-sizing: border-box !important;
}
.ev-logistic-section > .e-con-inner {
width: 100% !important;
max-width: 100% !important;
padding-left: 0 !important;
padding-right: 0 !important;
margin-left: auto !important;
margin-right: auto !important;
box-sizing: border-box !important;
}
.ev-logistic-section .elementor-element-343b363 {
--padding-left: 0px !important;
--padding-right: 0px !important;
padding-left: 0 !important;
padding-right: 0 !important;
width: 100% !important;
max-width: 100% !important;
box-sizing: border-box !important;
}
.ev-logistic-body-grid {
width: 100% !important;
max-width: 100% !important;
align-items: stretch !important;
}
.ev-logistic-content-col {
width: 100% !important;
max-width: 100% !important;
align-self: center !important;
}
.ev-feature-grid {
grid-template-columns: 1fr !important;
gap: 20px !important;
width: 100% !important;
max-width: 100% !important;
}
.ev-feature-card {
width: 100% !important;
max-width: 100% !important;
}
}
`}} />
<div className="elementor-61">
<div
ref={containerRef}
className="elementor-element elementor-element-88745f4 e-flex e-con-boxed cut-corner-no sticky-container-off e-con e-parent ev-logistic-section"
data-id="88745f4"
data-element_type="container"
data-e-type="container"
>
<div className="e-con-inner">
<div className="elementor-element elementor-element-343b363 e-con-full e-flex cut-corner-no sticky-container-off e-con e-child" data-id="343b363" data-element_type="container" data-e-type="container">
{/* Same header hierarchy and container structure as "The Doormile Way". */}
<div className="ev-logistic-header">
<div className="elementor-element elementor-element-7afb238 elementor-widget elementor-widget-logico_heading ev-logistic-kicker-widget" data-id="7afb238" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
<div className="elementor-widget-container">
<div className="logico-title ev-logistic-kicker">/ Built for Electric Vehicles /</div>
</div>
</div>
<div className="ev-logistic-title-wrapper">
<div className="elementor-element elementor-element-1cc335a elementor-widget elementor-widget-logico_heading ev-logistic-title-widget" data-id="1cc335a" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
<div className="elementor-widget-container">
<div
className="logico-title"
style={{
WebkitTextStroke: "4px #c01227",
color: "#fff",
fontWeight: 800,
}}
>
Logistics Built for EV Vehicles
</div>
</div>
</div>
</div>
</div>
<div className="ev-logistic-body-grid">
{/* Left Column: Enlarged Floating Wrapper & Ambient glow */}
<div className="ev-logistic-image-col">
<div className="ev-logistic-image-glow"></div>
<div ref={imageWrapperRef} className="ev-logistic-image-wrapper">
<Image
ref={imageRef}
src="/images/ev.webp"
alt="EV Logistics"
width={1050}
height={854}
priority
/>
</div>
</div>
{/* Right Column: 2x2 Grid of Feature Cards */}
<div className="ev-logistic-content-col">
<div className="ev-feature-grid">
{CARDS_DATA.map((item) => (
<div
key={item.index}
className="ev-feature-card"
>
<div className="ev-feature-icon-wrapper">
{item.icon}
</div>
<h4 className="ev-feature-card-title">{item.title}</h4>
<p className="ev-feature-card-desc">{item.desc}</p>
</div>
))}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
}