Files
doormile-next/src/components/sections/SolutionCard1.tsx
2026-06-01 20:20:14 +05:30

499 lines
18 KiB
TypeScript

"use client";
import React, { useState } from "react";
import IndustryWorldMap from "./IndustryWorldMap";
type Tab = "challenges" | "solutions";
interface Industry {
id: string;
tab: string;
eyebrow: string;
title: string;
image: string;
alt: string;
desc: string;
chips: [string, string];
challenges: string[];
solutions: string[];
}
const INDUSTRIES: Industry[] = [
{
id: "fmcg",
tab: "FMCG",
eyebrow: "Fast-Moving Consumer Goods",
title: "FMCG",
image: "/images/tab-pic-1-solution.jpeg",
alt: "FMCG logistics",
desc:
"FMCG logistics demands speed, precision, and continuous fulfillment across high-volume delivery networks — balancing tight timelines, inventory movement, and efficiency without compromising availability.",
chips: ["99.2% On-Time", "Live Route Sync"],
challenges: [
"Unpredictable demand spikes create delivery pressure during peak periods.",
"Fresh-product expiry constraints require faster, precisely timed deliveries.",
"Multi-stop route complexity increases travel time and coordination cost.",
"Inventory stockout risks rise when delays disrupt fast-moving distribution.",
],
solutions: [
"AI demand forecasting adapts delivery plans instantly to real-time order demand.",
"Expiry-aware routing prioritises perishable goods for on-time freshness.",
"Smart multi-stop optimisation groups orders to cut cost and travel time.",
"Real-time inventory sync prevents stockouts and improves fulfilment accuracy.",
],
},
{
id: "pharma",
tab: "Pharma",
eyebrow: "Pharmaceutical Logistics",
title: "Pharma",
image: "/images/tab-pic-2-solution.jpeg",
alt: "Pharma logistics",
desc:
"Pharma logistics requires precision, compliance, and real-time monitoring so every shipment arrives safely and on time — from temperature-sensitive medicines to urgent emergency deliveries.",
chips: ["Cold Chain Active", "Zero Delay SLA"],
challenges: [
"Cold chain integrity demands precise temperature control throughout transit.",
"Regulatory compliance must be tracked and documented on every delivery.",
"Critical delivery time windows require highly accurate scheduling.",
"Emergency shipments need instant dispatch and zero-delay execution.",
],
solutions: [
"Cold chain monitoring with automatic re-routing keeps shipments in-spec.",
"Compliance engine with audit trails ensures full chain-of-custody visibility.",
"Precision scheduling locks in critical delivery windows reliably.",
"Priority dispatch queue fast-tracks urgent, life-critical shipments.",
],
},
{
id: "b2b",
tab: "Enterprise & B2B",
eyebrow: "Enterprise & B2B",
title: "Enterprise & B2B",
image: "/images/tab-pic-3-solution.jpeg",
alt: "Enterprise and B2B logistics",
desc:
"Enterprise and B2B logistics require coordination and reliability to manage high-value shipments at scale — with appointment scheduling, white-glove standards, and strict SLA commitments.",
chips: ["SLA Guaranteed", "White-Glove Ready"],
challenges: [
"Appointment scheduling requires precise timing across many locations.",
"White-glove delivery standards demand premium handling and accuracy.",
"Multi-location routing complexity grows with large-scale operations.",
"Strict SLA commitments pressure teams to stay timely and error-free.",
],
solutions: [
"Intelligent appointment engine streamlines and automates delivery slots.",
"White-glove workflow module enforces premium handling end to end.",
"Enterprise route planner coordinates efficient multi-location delivery.",
"SLA monitoring dashboard tracks commitments and flags risk in real time.",
],
},
];
export default function SolutionCard1() {
const [active, setActive] = useState(0);
const [tab, setTab] = useState<Tab>("challenges");
const ind = INDUSTRIES[active];
const selectIndustry = (i: number) => {
setActive(i);
setTab("challenges"); // reset to Challenges on industry switch
};
return (
<>
<style dangerouslySetInnerHTML={{ __html: `
/* ============================================================
Solutions — Industry section (FMCG / Pharma / Enterprise & B2B)
Brand red #dc2626 / #ef4444 · bg #0d0d0d · Syne + DM Sans
============================================================ */
/* The theme forces Manrope on every element via a high-specificity
universal :not() !important rule; re-assert Syne / DM Sans from the
ID selector (which outranks it) directly on each text node. */
#ind-solutions .ind__eyebrow,
#ind-solutions .ind__title,
#ind-solutions .ind__tab,
#ind-solutions .ind__toggle-btn {
font-family: var(--font-syne), 'Syne', sans-serif !important;
}
#ind-solutions .ind__desc,
#ind-solutions .ind__chip,
#ind-solutions .ind__list li {
font-family: var(--font-dm-sans), 'DM Sans', sans-serif !important;
}
/* kit-5 also forces heading color/size on the title (an <h3>). */
#ind-solutions .ind__title {
color: #fff !important;
font-size: clamp(34px, 5.5vw, 68px) !important;
font-weight: 800 !important;
line-height: 1.02 !important;
margin: 0 0 16px !important;
letter-spacing: -0.01em !important;
}
#ind-solutions .ind__list li { color: #c9c9c9 !important; }
.ind {
position: relative;
isolation: isolate;
overflow: hidden;
background: #0d0d0d;
border-radius: clamp(16px, 2vw, 26px);
max-width: 1400px;
margin: clamp(24px, 4vw, 56px) auto;
padding: clamp(34px, 5vw, 76px) clamp(18px, 4vw, 64px);
}
.ind__map {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
opacity: 0.55;
z-index: 0;
pointer-events: none;
}
.ind__inner {
position: relative;
z-index: 1;
max-width: 1240px;
margin: 0 auto;
}
/* ---- Top tab bar ---- */
.ind__tabs {
display: flex;
gap: clamp(10px, 3vw, 36px);
border-bottom: 1px solid rgba(255,255,255,0.1);
margin-bottom: clamp(28px, 4vw, 52px);
flex-wrap: wrap;
}
.ind__tab {
appearance: none;
background: none;
border: none;
cursor: pointer;
padding: 10px 2px 16px;
font-weight: 700;
font-size: clamp(14px, 1.4vw, 18px);
color: #888;
position: relative;
letter-spacing: 0.01em;
transition: color 0.3s ease;
}
.ind__tab::after {
content: '';
position: absolute;
left: 0; right: 0; bottom: -1px;
height: 2px;
background: #dc2626;
transform: scaleX(0);
transform-origin: left;
transition: transform 0.35s cubic-bezier(.25,1,.5,1);
}
.ind__tab:hover { color: #ccc; }
.ind__tab.active { color: #fff; }
.ind__tab.active::after { transform: scaleX(1); }
/* ---- Grid ---- */
.ind__grid {
display: grid;
grid-template-columns: 0.9fr 1.1fr;
gap: clamp(28px, 4vw, 64px);
align-items: center;
}
/* ---- Left media ---- */
.ind__media {
position: relative;
display: flex;
align-items: center;
justify-content: center;
min-height: 300px;
}
.ind__glow {
position: absolute;
left: 50%; bottom: 4%;
width: 74%; height: 70px;
transform: translateX(-50%);
background: radial-gradient(50% 50% at 50% 50%, rgba(220,38,38,0.5), transparent 72%);
filter: blur(32px);
z-index: 0;
animation: indGlow 4s ease-in-out infinite;
}
.ind__img-wrap {
position: relative;
z-index: 1;
width: 100%;
max-width: 460px;
animation: indFloat 6s ease-in-out infinite;
will-change: transform;
}
.ind__img-wrap::before,
.ind__img-wrap::after {
content: '';
position: absolute;
width: 44px; height: 44px;
border: 2px solid #dc2626;
z-index: 3;
}
.ind__img-wrap::before {
top: -10px; left: -10px;
border-right: none; border-bottom: none;
border-radius: 10px 0 0 0;
}
.ind__img-wrap::after {
bottom: -10px; right: -10px;
border-left: none; border-top: none;
border-radius: 0 0 10px 0;
}
.ind__img {
display: block;
width: 100%;
height: auto;
border-radius: 12px;
object-fit: cover;
box-shadow: 0 30px 60px -25px rgba(0,0,0,0.7);
animation: indImgFade 0.55s ease both;
}
.ind__chip {
position: absolute;
z-index: 4;
display: inline-flex;
align-items: center;
gap: 8px;
padding: 9px 16px;
border-radius: 999px;
background: rgba(16,16,16,0.82);
border: 1px solid rgba(239,68,68,0.4);
backdrop-filter: blur(8px);
color: #fff;
font-weight: 500;
font-size: 13px;
white-space: nowrap;
box-shadow: 0 12px 28px -12px rgba(0,0,0,0.7);
animation: indFloat 6s ease-in-out infinite;
}
.ind__chip .dot {
width: 7px; height: 7px;
border-radius: 50%;
background: #ef4444;
box-shadow: 0 0 8px #ef4444;
animation: indDot 1.6s ease-in-out infinite;
}
.ind__chip--1 { top: 7%; left: -5%; animation-delay: 0.4s; }
.ind__chip--2 { bottom: 12%; right: -5%; animation-delay: 1.3s; }
/* ---- Right text ---- */
.ind__text { min-width: 0; }
.ind__eyebrow {
display: inline-flex;
align-items: center;
gap: 12px;
color: #ef4444;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.16em;
font-size: clamp(11px, 1vw, 13px);
margin-bottom: 14px;
}
.ind__eyebrow::before {
content: '';
width: 30px; height: 2px;
background: #ef4444;
}
.ind__desc {
color: #b4b4b4;
font-size: clamp(15px, 1.2vw, 18px);
line-height: 1.7;
font-weight: 400;
margin: 0 0 24px;
max-width: 580px;
}
/* ---- Challenges / Solutions toggle ---- */
.ind__toggle {
display: inline-flex;
gap: 4px;
padding: 5px;
border-radius: 999px;
background: rgba(255,255,255,0.05);
border: 1px solid rgba(255,255,255,0.09);
margin-bottom: 24px;
}
.ind__toggle-btn {
appearance: none;
border: none;
cursor: pointer;
padding: 9px 28px;
border-radius: 999px;
font-weight: 700;
font-size: 14px;
color: #9a9a9a;
background: transparent;
transition: color 0.3s ease, background-color 0.3s ease, box-shadow 0.3s ease;
}
.ind__toggle-btn:hover { color: #ddd; }
.ind__toggle-btn.active {
background: #dc2626;
color: #fff;
box-shadow: 0 8px 20px -8px rgba(220,38,38,0.6);
}
/* ---- Sliding panels ---- */
.ind__slider { overflow: hidden; }
.ind__track {
display: flex;
width: 200%;
transition: transform 0.4s cubic-bezier(.4,0,.2,1);
}
.ind__panel { width: 50%; flex: 0 0 50%; }
.ind__list { list-style: none; margin: 0; padding: 0; }
.ind__list li {
position: relative;
padding-left: 30px;
margin-bottom: 16px;
font-size: clamp(14px, 1.1vw, 16px);
line-height: 1.6;
opacity: 0;
transform: translateX(-16px);
}
.ind__list li:last-child { margin-bottom: 0; }
.ind__list li::before {
content: '';
position: absolute;
left: 4px; top: 8px;
width: 8px; height: 8px;
border-radius: 50%;
background: #dc2626;
box-shadow: 0 0 8px rgba(220,38,38,0.7);
}
.ind__panel.is-active .ind__list li {
animation: indBullet 0.5s cubic-bezier(.25,1,.5,1) forwards;
}
.ind__panel.is-active .ind__list li:nth-child(1) { animation-delay: 0.05s; }
.ind__panel.is-active .ind__list li:nth-child(2) { animation-delay: 0.13s; }
.ind__panel.is-active .ind__list li:nth-child(3) { animation-delay: 0.21s; }
.ind__panel.is-active .ind__list li:nth-child(4) { animation-delay: 0.29s; }
.ind__panel.is-active .ind__list li:nth-child(5) { animation-delay: 0.37s; }
@keyframes indFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-14px); } }
@keyframes indGlow { 0%,100% { opacity: 0.6; } 50% { opacity: 1; } }
@keyframes indDot { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }
@keyframes indBullet { to { opacity: 1; transform: translateX(0); } }
@keyframes indImgFade { from { opacity: 0; transform: scale(0.97); } to { opacity: 1; transform: scale(1); } }
/* ---- Responsive ---- */
@media (max-width: 900px) {
.ind__grid { grid-template-columns: 1fr; gap: clamp(40px, 8vw, 56px); }
.ind__media { order: -1; }
.ind__img-wrap { max-width: 380px; }
}
@media (max-width: 600px) {
.ind__chip { font-size: 12px; padding: 7px 12px; }
.ind__chip--1 { left: 0; }
.ind__chip--2 { right: 0; }
.ind__toggle-btn { padding: 9px 20px; }
}
@media (prefers-reduced-motion: reduce) {
.ind__img-wrap, .ind__glow, .ind__chip, .ind__chip .dot { animation: none !important; }
.ind__track { transition: none !important; }
.ind__panel.is-active .ind__list li { animation: none !important; opacity: 1; transform: none; }
}
`}} />
<section id="ind-solutions" className="ind" aria-label="Industry solutions">
<IndustryWorldMap />
<div className="ind__inner">
{/* Top tab bar */}
<div className="ind__tabs" role="tablist" aria-label="Industries">
{INDUSTRIES.map((it, i) => (
<button
key={it.id}
type="button"
role="tab"
aria-selected={i === active}
className={`ind__tab ${i === active ? "active" : ""}`}
onClick={() => selectIndustry(i)}
>
{it.tab}
</button>
))}
</div>
<div className="ind__grid">
{/* Left media */}
<div className="ind__media">
<div className="ind__glow" />
<div className="ind__img-wrap">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img key={active} className="ind__img" src={ind.image} alt={ind.alt} decoding="async" />
</div>
<div className="ind__chip ind__chip--1">
<span className="dot" />
{ind.chips[0]}
</div>
<div className="ind__chip ind__chip--2">
<span className="dot" />
{ind.chips[1]}
</div>
</div>
{/* Right text */}
<div className="ind__text">
<span className="ind__eyebrow">{ind.eyebrow}</span>
<h3 className="ind__title">{ind.title}</h3>
<p className="ind__desc">{ind.desc}</p>
<div className="ind__toggle" role="tablist" aria-label="Challenges or Solutions">
<button
type="button"
role="tab"
aria-selected={tab === "challenges"}
className={`ind__toggle-btn ${tab === "challenges" ? "active" : ""}`}
onClick={() => setTab("challenges")}
>
Challenges
</button>
<button
type="button"
role="tab"
aria-selected={tab === "solutions"}
className={`ind__toggle-btn ${tab === "solutions" ? "active" : ""}`}
onClick={() => setTab("solutions")}
>
Solutions
</button>
</div>
<div className="ind__slider">
<div
className="ind__track"
key={active}
style={{ transform: tab === "challenges" ? "translateX(0)" : "translateX(-50%)" }}
>
<div className={`ind__panel ${tab === "challenges" ? "is-active" : ""}`}>
<ul className="ind__list">
{ind.challenges.map((c, idx) => (
<li key={idx}>{c}</li>
))}
</ul>
</div>
<div className={`ind__panel ${tab === "solutions" ? "is-active" : ""}`}>
<ul className="ind__list">
{ind.solutions.map((s, idx) => (
<li key={idx}>{s}</li>
))}
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</>
);
}