248 lines
9.2 KiB
TypeScript
248 lines
9.2 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import { motion, AnimatePresence } from "framer-motion";
|
|
import StrategySection from "../strategy/StrategySection";
|
|
|
|
export default function Workflow3() {
|
|
const [activeSlide, setActiveSlide] = useState(0);
|
|
const [paused, setPaused] = useState(false);
|
|
|
|
const slides = [
|
|
{
|
|
title: "STRATEGY",
|
|
text: "Our grading engine continuously evaluates fulfillment performance, SLA compliance, and route efficiency before every dispatch. By comparing legacy routing methods with unified optimization, the system ensures smarter and more reliable delivery planning. This helps businesses maintain operational consistency while improving overall delivery performance."
|
|
},
|
|
{
|
|
title: "STRATEGY",
|
|
text: "Every EV route is pre-validated against real battery capacity and charging feasibility before a rider leaves the hub. This reduces the risk of delivery interruptions, charging failures, or delayed orders during operations. The platform ensures reliable route execution while maximizing EV fleet efficiency and rider confidence."
|
|
},
|
|
{
|
|
title: "STRATEGY",
|
|
text: "The system provides actionable fleet insights and optimized workload distribution to improve both rider experience and operational productivity. Balanced route allocation helps reduce rider fatigue, improve retention, and maintain consistent delivery quality across zones. Managers gain better visibility into fleet performance, enabling faster and more informed decision-making."
|
|
}
|
|
];
|
|
|
|
// Always begin the storytelling sequence from slide 1 (01/03) on mount — never
|
|
// preserve a previous slide index across remounts / route changes back to MileTruth.
|
|
useEffect(() => {
|
|
setActiveSlide(0);
|
|
}, []);
|
|
|
|
// Auto-advance the carousel every 4s, infinite loop. Keyed on activeSlide so any
|
|
// manual selection resets the timer; pauses while the user hovers the card.
|
|
useEffect(() => {
|
|
if (paused) return;
|
|
const id = setTimeout(() => {
|
|
setActiveSlide((prev) => (prev + 1) % slides.length);
|
|
}, 4000);
|
|
return () => clearTimeout(id);
|
|
}, [activeSlide, paused, slides.length]);
|
|
|
|
return (
|
|
<section className="dm-wf3" aria-label="Workflow 3 — Happier Riders. Higher Fulfillment. & Strategy">
|
|
|
|
{/* ── Top sub-section: the full "Happier Riders. Higher Fulfillment."
|
|
3D scroll-storytelling experience ── */}
|
|
<StrategySection connected />
|
|
|
|
{/* ── Bottom sub-section: Strategy content, flush + pulled up to butt against
|
|
the 3D card's flat bottom so the whole workflow reads as one container —
|
|
the same connected structure used in Workflow 1 & 2 ── */}
|
|
<div className="dm-wf3-card" onMouseEnter={() => setPaused(true)} onMouseLeave={() => setPaused(false)}>
|
|
{/* Left Column: Overlapping Chevron Graphic */}
|
|
<div className="dm-workflow-left">
|
|
<svg viewBox="0 0 320 280" fill="none" xmlns="http://www.w3.org/2000/svg" className="dm-workflow-svg">
|
|
<path
|
|
d="M 30,20 C 22,20 16,26 16,34 L 78,85 C 81,88 81,92 78,95 L 16,146 C 16,154 22,160 30,160 L 130,160 C 138,160 145,154 148,146 L 204,95 C 207,92 207,88 204,85 L 148,34 C 145,26 138,20 130,20 Z"
|
|
stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.25"
|
|
/>
|
|
<path
|
|
d="M 110,100 C 102,100 96,106 96,114 L 158,165 C 161,168 161,172 158,175 L 96,226 C 96,234 102,240 110,240 L 210,240 C 218,240 225,234 228,226 L 284,175 C 287,172 287,168 284,165 L 228,114 C 225,106 218,100 210,100 Z"
|
|
stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.85"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
|
|
{/* Right Column: Quotes & Text Content */}
|
|
<div className="dm-workflow-right">
|
|
<svg width="32" height="24" viewBox="0 0 32 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="dm-workflow-quote">
|
|
<rect x="2" y="2" width="9" height="20" rx="1.5" transform="skewX(-12)" fill="#C01227" />
|
|
<rect x="16" y="2" width="9" height="20" rx="1.5" transform="skewX(-12)" fill="#C01227" />
|
|
</svg>
|
|
|
|
<h3 className="dm-workflow-title">{slides[activeSlide].title}</h3>
|
|
|
|
<div className="dm-workflow-text-container">
|
|
<AnimatePresence mode="wait">
|
|
<motion.p
|
|
key={activeSlide}
|
|
initial={{ opacity: 0, y: 12 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0, y: -12 }}
|
|
transition={{ duration: 0.7, ease: "easeInOut" }}
|
|
className="dm-workflow-text"
|
|
>
|
|
{slides[activeSlide].text}
|
|
</motion.p>
|
|
</AnimatePresence>
|
|
</div>
|
|
|
|
<div className="dm-workflow-nav">
|
|
<span className="dm-workflow-counter">0{activeSlide + 1}/03</span>
|
|
<div className="dm-workflow-bars">
|
|
{slides.map((_, index) => (
|
|
<button
|
|
key={index}
|
|
type="button"
|
|
aria-label={`Go to slide ${index + 1}`}
|
|
className={`dm-workflow-bar ${index === activeSlide ? "is-active" : ""}`}
|
|
onClick={() => setActiveSlide(index)}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style dangerouslySetInnerHTML={{ __html: styles }} />
|
|
</section>
|
|
);
|
|
}
|
|
|
|
const styles = `
|
|
/* ============================================================
|
|
Workflow 3 = ONE container:
|
|
├─ Happier Riders. Higher Fulfillment. (full StrategySection — 3D)
|
|
└─ Strategy (content card, flush, pulled up)
|
|
The Strategy card aligns to the 3D card's 20px side insets, butts against
|
|
its flat bottom and rounds the bottom corners, so the two read as a single
|
|
continuous container — same technique as Workflow 1 & 2.
|
|
============================================================ */
|
|
.dm-wf3 {
|
|
position: relative;
|
|
margin: 0 auto 0;
|
|
}
|
|
|
|
/* Cancel the global "section { padding: 6rem 0 }" (consolidated into /public/css/site.css): both
|
|
this wrapper and the nested .dm-st are sections, so that 96px top+bottom stacked
|
|
into large empty bands above / between the workflows. These are full-bleed pinned
|
|
experiences whose cards butt together via their own insets — no section padding. */
|
|
.dm-wf3, .dm-wf3 .dm-st { padding-top: 0; padding-bottom: 0; }
|
|
|
|
.dm-wf3-card {
|
|
position: relative;
|
|
z-index: 2;
|
|
margin: 0 20px 0;
|
|
background: #181818;
|
|
border: 1px solid rgba(255, 255, 255, 0.06);
|
|
border-top: none;
|
|
border-radius: 0 0 28px 28px;
|
|
/* No shadow: this card is flush under the strategy 3D card and merges with it as one
|
|
continuous container — a shadow here would re-introduce a dark band at the seam. */
|
|
box-shadow: none;
|
|
padding: 36px 60px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 40px;
|
|
overflow: hidden;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.dm-workflow-left {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
max-width: 440px;
|
|
}
|
|
.dm-workflow-svg {
|
|
width: 100%;
|
|
height: auto;
|
|
filter: drop-shadow(0 8px 24px rgba(0,0,0,0.3));
|
|
}
|
|
|
|
.dm-workflow-right {
|
|
flex: 1.2;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
gap: 20px;
|
|
}
|
|
.dm-workflow-quote { margin-bottom: 5px; }
|
|
|
|
.dm-workflow-title {
|
|
font-family: var(--font-space-grotesk), var(--font-manrope), system-ui, sans-serif;
|
|
font-size: 38px;
|
|
font-weight: 700;
|
|
color: #F8FAFC !important;
|
|
letter-spacing: -0.015em;
|
|
margin: 0 !important;
|
|
padding: 0 !important;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.dm-workflow-text-container { min-height: 150px; width: 100%; }
|
|
.dm-workflow-text {
|
|
font-family: var(--font-manrope), system-ui, sans-serif;
|
|
font-size: 21px;
|
|
line-height: 1.75;
|
|
letter-spacing: 0.01em;
|
|
color: #A3A3A3;
|
|
margin: 0 !important;
|
|
padding: 0 !important;
|
|
}
|
|
|
|
.dm-workflow-nav {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-end;
|
|
gap: 10px;
|
|
align-self: flex-end;
|
|
margin-top: 10px;
|
|
}
|
|
.dm-workflow-counter {
|
|
font-family: var(--font-space-grotesk), sans-serif;
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
color: #737373;
|
|
letter-spacing: 0.08em;
|
|
}
|
|
.dm-workflow-bars { display: flex; gap: 8px; }
|
|
.dm-workflow-bar {
|
|
width: 40px;
|
|
height: 3px;
|
|
border: none;
|
|
padding: 0;
|
|
background: rgba(255, 255, 255, 0.15);
|
|
border-radius: 999px;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
.dm-workflow-bar.is-active { background: #C01227; }
|
|
.dm-workflow-bar:hover { background: rgba(255, 255, 255, 0.35); }
|
|
.dm-workflow-bar.is-active:hover { background: #C01227; }
|
|
|
|
/* ── Responsive — keep insets/radius aligned to the 3D card ── */
|
|
@media (max-width: 1024px) {
|
|
.dm-wf3-card { padding: 44px 44px; gap: 44px; }
|
|
.dm-workflow-title { font-size: 32px; }
|
|
.dm-workflow-text { font-size: 19px; }
|
|
}
|
|
@media (max-width: 767px) {
|
|
.dm-wf3-card {
|
|
margin: 0 10px 0;
|
|
border-radius: 0 0 20px 20px;
|
|
padding: 36px 28px;
|
|
gap: 36px;
|
|
flex-direction: column;
|
|
}
|
|
.dm-workflow-left { max-width: 280px; }
|
|
.dm-workflow-right { width: 100%; }
|
|
.dm-workflow-title { font-size: 28px; }
|
|
.dm-workflow-text { font-size: 17px; }
|
|
.dm-workflow-text-container { min-height: auto; }
|
|
}
|
|
`;
|