Files
REXNT/src/Components/Sections/DepartmentDetail5/DepartmentDetail5.jsx
Rahaf 69a2ed83c5
All checks were successful
Build frontend / build (push) Successful in 25s
Added images for cdn and edit Imagepreload
2026-01-20 22:54:08 +03:00

622 lines
35 KiB
JavaScript

import React, { useState, useEffect, useRef, useCallback } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { useTranslation } from "react-i18next";
// import d18 from "../../../../src/assets/Images/d18.jpg";
// import d25 from "../../../../src/assets/Images/d25.jpeg";
// import d26 from "../../../../src/assets/Images/d26.jpeg";
const d18="https://i.imgur.com/ZhYek8J.jpeg";
const d25="https://i.imgur.com/Bte4bPE.jpeg";
const d26="https://i.imgur.com/QlbXMye.jpeg";
function ProjectsTimeline({
projects,
mainTitle = "المشاريع المنفذة",
subtitle = "خط زمني شامل للأعمال والإنجازات",
plain = false,
rtl = true
}) {
const wrapperRef = useRef(null);
const scrollRef = useRef(null);
const svgRef = useRef(null);
const [itemsRefs, setItemsRefs] = useState([]);
const [currentIndex, setCurrentIndex] = useState(0);
useEffect(() => {
setItemsRefs((r) => {
const arr = Array(projects.length)
.fill()
.map((_, i) => r[i] || React.createRef());
return arr;
});
}, [projects.length]);
const drawCurvedLines = useCallback(() => {
const svgEl = svgRef.current;
const wrapper = wrapperRef.current;
if (!svgEl || !wrapper) return;
while (svgEl.firstChild) svgEl.removeChild(svgEl.firstChild);
svgEl.setAttribute("width", wrapper.scrollWidth);
svgEl.setAttribute("height", wrapper.offsetHeight);
if (!itemsRefs || itemsRefs.length < 2) return;
const svgNS = "http://www.w3.org/2000/svg";
const defs = document.createElementNS(svgNS, "defs");
const gradient = document.createElementNS(svgNS, "linearGradient");
gradient.setAttribute("id", "timeline-gradient");
gradient.setAttribute("x1", "0%");
gradient.setAttribute("y1", "0%");
gradient.setAttribute("x2", "100%");
gradient.setAttribute("y2", "0%");
const stop1 = document.createElementNS(svgNS, "stop");
stop1.setAttribute("offset", "0%");
stop1.setAttribute("style", "stop-color:#0f172a;stop-opacity:1");
const stop2 = document.createElementNS(svgNS, "stop");
stop2.setAttribute("offset", "50%");
stop2.setAttribute("style", "stop-color:#f97316;stop-opacity:1");
const stop3 = document.createElementNS(svgNS, "stop");
stop3.setAttribute("offset", "100%");
stop3.setAttribute("style", "stop-color:#9ca3af;stop-opacity:1");
gradient.appendChild(stop1);
gradient.appendChild(stop2);
gradient.appendChild(stop3);
defs.appendChild(gradient);
svgEl.appendChild(defs);
for (let i = 0; i < itemsRefs.length - 1; i++) {
const item1 = itemsRefs[i].current;
const item2 = itemsRefs[i + 1].current;
if (!item1 || !item2) continue;
const circle1 = item1.querySelector(".year-circle");
const circle2 = item2.querySelector(".year-circle");
if (!circle1 || !circle2) continue;
const rect1 = circle1.getBoundingClientRect();
const rect2 = circle2.getBoundingClientRect();
const wrapperRect = wrapper.getBoundingClientRect();
const x1 = rect1.left - wrapperRect.left + rect1.width / 2;
const y1 = rect1.top - wrapperRect.top + rect1.height / 2;
const x2 = rect2.left - wrapperRect.left + rect2.width / 2;
const y2 = rect2.top - wrapperRect.top + rect2.height / 2;
const controlPointOffset = Math.abs(x2 - x1) * 0.4;
const cx1 = x1 - controlPointOffset;
const cy1 = y1 - 40;
const cx2 = x2 + controlPointOffset;
const cy2 = y2 - 40;
const path = document.createElementNS(svgNS, "path");
const d = `M ${x1} ${y1} C ${cx1} ${cy1}, ${cx2} ${cy2}, ${x2} ${y2}`;
path.setAttribute("d", d);
path.setAttribute("stroke", "url(#timeline-gradient)");
path.setAttribute("stroke-width", "4");
path.setAttribute("fill", "none");
path.setAttribute("stroke-linecap", "round");
path.style.filter = "drop-shadow(0 2px 8px rgba(15,23,42,0.22))";
svgEl.appendChild(path);
}
}, [itemsRefs]);
const setActiveItem = useCallback(
(index) => {
setCurrentIndex(index);
itemsRefs.forEach((ref, i) => {
const el = ref.current;
if (!el) return;
if (i === index) el.classList.add("active");
else el.classList.remove("active");
});
},
[itemsRefs]
);
const scrollToItem = useCallback(
(index) => {
if (index < 0 || index >= itemsRefs.length) return;
const scrollContainer = scrollRef.current;
const item = itemsRefs[index].current;
if (!scrollContainer || !item) return;
const itemRect = item.getBoundingClientRect();
const containerRect = scrollContainer.getBoundingClientRect();
const scrollLeft = scrollContainer.scrollLeft;
const targetScroll =
scrollLeft + itemRect.left - containerRect.left - containerRect.width / 2 + itemRect.width / 2;
scrollContainer.scrollTo({ left: targetScroll, behavior: "smooth" });
setActiveItem(index);
},
[itemsRefs, setActiveItem]
);
const onPrev = () => {
if (currentIndex > 0) scrollToItem(currentIndex - 1);
};
const onNext = () => {
if (currentIndex < itemsRefs.length - 1) scrollToItem(currentIndex + 1);
};
useEffect(() => {
const t = setTimeout(() => {
drawCurvedLines();
setActiveItem(0);
}, 100);
const scrollContainer = scrollRef.current;
let scrollTimeout = null;
const onScroll = () => {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => {
const containerRect = scrollContainer.getBoundingClientRect();
const containerCenter = containerRect.left + containerRect.width / 2;
let closestIndex = 0;
let closestDistance = Infinity;
itemsRefs.forEach((ref, index) => {
const el = ref.current;
if (!el) return;
const itemRect = el.getBoundingClientRect();
const itemCenter = itemRect.left + itemRect.width / 2;
const distance = Math.abs(containerCenter - itemCenter);
if (distance < closestDistance) {
closestDistance = distance;
closestIndex = index;
}
});
if (closestIndex !== currentIndex) {
setActiveItem(closestIndex);
}
}, 150);
};
if (scrollContainer) scrollContainer.addEventListener("scroll", onScroll);
const onResize = () => setTimeout(drawCurvedLines, 120);
window.addEventListener("resize", onResize);
return () => {
clearTimeout(t);
if (scrollContainer) scrollContainer.removeEventListener("scroll", onScroll);
window.removeEventListener("resize", onResize);
};
}, [itemsRefs, drawCurvedLines, setActiveItem]);
useEffect(() => {
setTimeout(() => drawCurvedLines(), 120);
}, [itemsRefs, drawCurvedLines, projects.length]);
const css = `
:root{--bg-start:#0b1220;--bg-mid:#102033;--bg-end:#2b3a4a;--accent:#f97316;--muted:#9ca3af}
.projects-timeline-root { direction: ${rtl ? "rtl" : "ltr"}; min-height: 100%; }
.timeline-scroll { overflow-x: auto; overflow-y: hidden; scroll-behavior: smooth; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.timeline-scroll::-webkit-scrollbar{ display:none; height:0; }
.timeline-wrapper { display:flex; align-items:center; position:relative; padding:clamp(48px,6vw,120px) clamp(12px,4vw,120px); min-width:max-content; }
.svg-container { position:absolute; top:0; left:0; width:100%; height:100%; pointer-events:none; z-index:0; }
.timeline-item { position:relative; display:flex; flex-direction:column; align-items:center; margin:0 clamp(20px,4vw,60px); transition:all .6s cubic-bezier(.34,1.56,.64,1); z-index:1; flex:0 0 auto; }
.year-circle { width:clamp(72px,9vw,150px); height:clamp(72px,9vw,150px); border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:clamp(14px,1.6vw,24px); font-weight:700; background: linear-gradient(135deg, rgba(255,255,255,0.04), rgba(255,255,255,0.02)); color:var(--bg-start); box-shadow: 0 6px 30px rgba(2,6,23,0.6), inset 0 1px 0 rgba(255,255,255,0.04); transition:all .6s cubic-bezier(.34,1.56,.64,1); cursor:pointer; border:1px solid rgba(255,255,255,0.08); position:relative; z-index:2; backdrop-filter: blur(8px) saturate(120%);
background-clip: padding-box;
}
.year-circle::after { content: ''; position:absolute; inset:-8px; border-radius:50%; border:2px solid rgba(249,115,22,0.08); opacity:0; transition:all .6s ease; }
.timeline-item.active .year-circle { width:clamp(110px,14vw,200px); height:clamp(110px,14vw,200px); font-size:clamp(18px,2.2vw,28px); box-shadow:0 18px 60px rgba(15,23,42,.5), inset 0 2px 6px rgba(255,255,255,0.04); border-color: rgba(249,115,22,0.18); transform: translateY(-15px) scale(1.03); }
.timeline-item.active .year-circle::after { opacity:1; inset:-12px; animation: ripple 2s ease-out infinite; }
@keyframes ripple { 0%{ transform: scale(1); opacity:.6;} 100%{ transform: scale(1.25); opacity:0;} }
.project-card { margin-top:40px; background: linear-gradient(180deg, rgba(255,255,255,0.06), rgba(255,255,255,0.03)); border-radius:18px; padding:26px; min-width:320px; max-width:420px; box-shadow:0 12px 40px rgba(2,6,23,.45); opacity:.9; transform: scale(.98) translateY(8px); transition:all .6s cubic-bezier(.34,1.56,.64,1); border:1px solid rgba(255,255,255,.06); position:relative; overflow:hidden; backdrop-filter: blur(8px) saturate(120%); box-sizing: border-box; }
.project-card::before { content:''; position:absolute; top:0; left:0; right:0; height:4px; background: linear-gradient(to left, var(--accent), #b91c1c, var(--muted)); opacity:0; transition:opacity .6s ease; }
.timeline-item.active .project-card { opacity:1; transform: scale(1) translateY(0); box-shadow:0 28px 80px rgba(2,6,23,.5),0 6px 18px rgba(0,0,0,.08); border-color: rgba(249,115,22,.14); }
.timeline-item.active .project-card::before { opacity:1; }
.project-text { font-size:15px; line-height:2; color:#0b1220; font-weight:600; text-align: ${rtl ? "right" : "left"}; }
.project-text li { margin-bottom:12px; padding-inline:12px; transition:all .3s ease; border-radius:8px; padding:8px 12px; }
.timeline-item.active .project-text li:hover { background: rgba(249,115,22,.06); transform: translateX(${rtl ? "-4px" : "4px"}); }
.scroll-indicator { position:absolute; bottom:30px; left:50%; transform: translateX(-50%); display:flex; gap:20px; z-index:10; }
.scroll-btn { background: linear-gradient(135deg, rgba(255,255,255,.9) 0%, rgba(255,255,255,.82) 100%); border:none; border-radius:50%; width:56px; height:56px; display:flex; align-items:center; justify-content:center; cursor:pointer; font-size:22px; color:var(--accent); box-shadow:0 6px 20px rgba(2,6,23,.35); transition:all .4s cubic-bezier(.34,1.56,.64,1); backdrop-filter: blur(6px); }
.scroll-btn:hover:not(:disabled){ background: linear-gradient(135deg,#fff 0%,#fff8f2 100%); transform: scale(1.12); box-shadow:0 10px 35px rgba(15,23,42,.22); }
.scroll-btn:active:not(:disabled){ transform: scale(1.05); }
.scroll-btn:disabled { opacity:.4; cursor:not-allowed; }
@media (max-width:768px){
.timeline-wrapper { padding:clamp(18px,4vw,36px) 16px; align-items:flex-start; }
.timeline-item { margin:0 12px; }
.year-circle { width:64px !important; height:64px !important; font-size:13px !important; }
.timeline-item.active .year-circle { width:96px !important; height:96px !important; font-size:16px !important; transform: translateY(-10px) scale(1.02); }
.project-card { width: clamp(160px, 72vw, 300px); padding:16px; margin-top:18px; }
.project-text { font-size:13px; line-height:1.6; }
.scroll-btn { width:44px; height:44px; font-size:18px; }
.scroll-indicator { position:relative; bottom:auto; left:auto; transform:none; margin:12px auto 0; justify-content:center; }
.projects-timeline-root { overflow-y: hidden; }
}
@media (max-width:420px){
.timeline-wrapper { padding:18px 12px; }
.timeline-item { margin:0 8px; }
.project-card { width: calc(100vw - 56px); max-width:320px; min-width:140px; padding:12px; margin-top:12px; border-radius:14px; }
.project-text { font-size:12px; line-height:1.4; }
.project-text li { margin-bottom:8px; padding-inline:10px; padding:6px 10px; }
.year-circle { width:56px !important; height:56px !important; font-size:12px !important; }
.timeline-item.active .year-circle { width:88px !important; height:88px !important; font-size:15px !important; transform: translateY(-8px) scale(1.02); }
.svg-container { display:block; }
.scroll-indicator { bottom:12px; }
}
.projects-timeline-root.plain-bleed .timeline-wrapper { padding:clamp(48px,6vw,120px) 24px; }
.projects-timeline-root.plain-bleed .project-card { max-width:420px; }
`;
const mainStyle = plain ? { background: "#ffffff", paddingBottom: 0 } : { background: "linear-gradient(135deg, var(--bg-start) 0%, var(--bg-mid) 30%, var(--bg-end) 60%)" };
return (
<div className={`projects-timeline-root w-full h-full ${plain ? "plain-bleed" : ""}`}>
<style>{css}</style>
<main className="w-full h-full overflow-hidden" style={mainStyle}>
<div className="h-full flex flex-col">
{!plain && (
<header className="text-center py-8 px-4">
<h1 id="main-title" className={` ${plain ? "text-3xl md:text-4xl font-bold text-gray-900" : "text-5xl font-bold text-white"} mb-3`} style={plain ? { textShadow: "none" } : { textShadow: "0 4px 20px rgba(0,0,0,0.3)" }}>
{mainTitle}
</h1>
<p id="subtitle" className={`${plain ? "text-base text-gray-700" : "text-xl text-white opacity-90"}`}>{subtitle}</p>
</header>
)}
<div className="flex-1 relative">
<div className="timeline-scroll h-full" id="timeline-scroll" ref={scrollRef} aria-label={rtl ? "خط زمني قابل للتمرير" : "Scrollable timeline"}>
<div className="timeline-wrapper" id="timeline-wrapper" ref={wrapperRef}>
<svg className="svg-container" id="timeline-svg" ref={svgRef} />
{projects.map((project, idx) => (
<div
className="timeline-item"
key={idx}
ref={itemsRefs[idx]}
data-index={idx}
onClick={() => scrollToItem(idx)}
role="button"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") scrollToItem(idx);
}}
>
<div className="year-circle">{project.year}</div>
<div className="project-card">
<ul className="project-text" aria-live="polite">
{project.items.map((it, i) => (
<li key={i}> {it}</li>
))}
</ul>
</div>
</div>
))}
</div>
</div>
<div className="scroll-indicator">
<button className="scroll-btn" aria-label={rtl ? "السابق" : "Previous"} onClick={onPrev} disabled={currentIndex === 0} title={rtl ? "السابق" : "Previous"}></button>
<button className="scroll-btn" aria-label={rtl ? "التالي" : "Next"} onClick={onNext} disabled={currentIndex === projects.length - 1} title={rtl ? "التالي" : "Next"}></button>
</div>
</div>
</div>
</main>
</div>
);
}
const defaultProjects = [
{
year: "2009-2010",
items: [
"تدقيق ومطابقة المخططات الهندسية والتكنولوجية لخطوط الدرفلة وصهر الحد - الشركة المصنعة: دانييلي (إيطاليا) 2009-2010"
]
},
{
year: "2007-2008",
items: [
"تدقيق ومطابقة المخططات الهندسية والتكنولوجية - الشركة المصنعة: SMS (إيطاليا) 2007-2008"
]
},
{
year: "2015",
items: [
"التفتيش والاختبارات لخطوط والخزانات لدى الشركة السورية لنقل النفط (2015)"
]
},
{
year: "2018",
items: [
"التفتيش الفني والاختبارات لخزانات غاز الراموسة في حلب (2018)"
]
},
{
year: "2022",
items: [
"التفتيش الفني والاختبارات لقواعد وهيكل الفرن في معمل المتحدة للأسمنت - أبو الشامات (2022)"
]
},
{
year: "2017-2019",
items: [
"التفتيش الفني والاختبارات لخزانات شركة محروقات سادكوب شنشار - بوقا - عدرا (2017-2019)"
]
},
{
year: "2023-2024",
items: [
"إجراء الفحص الفني لخزانات مستودعات وقود MTN-SYRIATEL الاستراتيجية والثانوية (2023-2024)"
]
}
];
export default function DepartmentDetail5() {
const { t, i18n } = useTranslation();
const [active, setActive] = useState(null);
const isRTL = typeof i18n.dir === "function" ? i18n.dir() === "rtl" : (i18n.language || "").startsWith("ar");
const dir = isRTL ? "rtl" : "ltr";
const buttons = [
{ id: 1, title: t("departmentDetail5.buttons.1"), key: "expertise", img: d25 },
{ id: 3, title: t("departmentDetail5.buttons.3"), key: "works", img: d26 }
];
const expertiseItemsRaw = t("departmentDetail5.expertiseItems", { returnObjects: true });
const expertiseItems = Array.isArray(expertiseItemsRaw) && expertiseItemsRaw.length > 0 ? expertiseItemsRaw : [
"إجراء الفحوصات غير الإتلافية (NDT) للكشف عن العيوب الخفية في المكونات المعدنية.",
"فحص اللحامات باستخدام:",
"Ultrasonic Testing (UT) - الفحص بالموجات فوق الصوتية.",
"Magnetic Particle Testing (MT) - الفحص بالجسيمات المغناطيسية.",
"Penetrant Testing (PT) - الفحص بالسوائل المتغلغلة.",
"Visual Testing (VT) - الفحص البصري وتقييم جودة اللحام ومطابقته للمواصفات.",
"تدقيق ومطابقة المخططات التكنولوجية والهندسية لأعمال التصنيع المعدني، الميكانيكي، الكهربائي ومنظومات التحكم.",
"تدقيق ومطابقة جاهزية المعدات الهندسية وملائمتها للمعايير العالمية.",
"الالتزام بتطبيق معايير السلامة المهنية والجودة أثناء تنفيذ أعمال التفتيش."
];
const displayItems = expertiseItems.map((text, idx) => {
const icons = [
(<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24" key={`ic-${idx}-1`}><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M12 8v4l3 3" /></svg>),
(<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24" key={`ic-${idx}-2`}><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M3 7h18M3 12h18M3 17h18" /></svg>),
(<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24" key={`ic-${idx}-3`}><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M12 2l3 7h7l-5.5 4 2 7L12 17l-6.5 3 2-7L2 9h7z" /></svg>),
(<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24" key={`ic-${idx}-4`}><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M12 2l3 7h7l-5.5 4 2 7L12 17l-6.5 3 2-7L2 9h7z" /></svg>),
(<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24" key={`ic-${idx}-5`}><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M4 7h16M4 12h16M4 17h8" /></svg>)
];
const icon = icons[idx % icons.length] || icons[0];
return { icon, text };
});
const timelineProjectsRaw = t("departmentDetail5.projectsTimeline.defaultProjects", { returnObjects: true });
const timelineProjects = Array.isArray(timelineProjectsRaw) && timelineProjectsRaw.length > 0 ? timelineProjectsRaw : defaultProjects;
const heroImage = active === "expertise" ? d25 : active === "works" ? d26 : d18;
const handleButtonClick = (key) => {
setActive((prev) => (prev === key ? null : key));
};
return (
<div dir={dir} className="w-full min-h-screen bg-white pb-12">
<section className="relative">
<div className="w-full">
<AnimatePresence mode="wait">
<motion.div
key={active}
initial={{ opacity: 0, scale: 1.05 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.98 }}
transition={{ duration: 0.6 }}
className="relative h-72 sm:h-80 md:h-[480px] lg:h-[580px] overflow-visible"
>
<img
src={heroImage}
alt={t("departmentDetail5.hero.heroAlt")}
className="absolute inset-0 w-full h-full object-cover object-center z-0 brightness-90"
/>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.25, duration: 0.45 }}
className="absolute inset-0 bg-gradient-to-r from-slate-900/90 via-slate-800/75 to-slate-900/60 z-5"
/>
<div className="absolute inset-0 z-10 flex items-center pointer-events-none">
<div className="max-w-7xl mx-auto px-4 sm:px-6 w-full">
<AnimatePresence mode="wait">
{active === "expertise" ? (
<motion.div key="expertise-title" initial={{ opacity: 0, x: -50 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: 50 }} transition={{ duration: 0.5 }} className="text-white max-w-4xl">
<div className="inline-block mb-4 px-5 py-2 bg-gradient-to-r from-amber-500 to-orange-600 rounded-full text-xs sm:text-sm font-bold tracking-wide shadow-2xl">{t("departmentDetail5.hero.expertiseBadge")}</div>
<h2 className="text-xl sm:text-2xl md:text-4xl lg:text-5xl font-extrabold drop-shadow-2xl leading-tight mb-3 sm:mb-6">{t("departmentDetail5.hero.expertiseTitle")}</h2>
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">{t("departmentDetail5.hero.expertiseSubtitle")}</p>
</motion.div>
) : active === "works" ? (
<motion.div key="works-title" initial={{ opacity: 0, x: -50 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: 50 }} transition={{ duration: 0.5 }} className="text-white max-w-4xl">
<div className="inline-block mb-4 px-5 py-2 bg-gradient-to-r from-amber-500 to-orange-600 rounded-full text-xs sm:text-sm font-bold tracking-wide shadow-2xl">{t("departmentDetail5.hero.worksBadge")}</div>
<h2 className="text-xl sm:text-2xl md:text-4xl lg:text-5xl font-extrabold drop-shadow-2xl leading-tight mb-3 sm:mb-6">{t("departmentDetail5.hero.worksTitle")}</h2>
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">{t("departmentDetail5.hero.worksSubtitle")}</p>
</motion.div>
) : (
<motion.div key="default-title" initial={{ opacity: 0, x: -50 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: 50 }} transition={{ duration: 0.5 }} className="text-white max-w-4xl">
<h2 className="text-xl sm:text-2xl md:text-4xl lg:text-5xl font-extrabold drop-shadow-2xl leading-tight">{t("departmentDetail5.hero.defaultTitle")}</h2>
</motion.div>
)}
</AnimatePresence>
</div>
</div>
<div className="absolute left-1/2 bottom-0 transform -translate-x-1/2 translate-y-1/2 w-full px-4 pointer-events-auto hidden md:block" style={{ zIndex: 99999 }}>
<AnimatePresence>
{!active && (
<motion.div
key="floating-buttons"
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
transition={{ duration: 0.45 }}
className="w-full max-w-7xl mx-auto"
>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 sm:gap-6">
{buttons.map((b, index) => (
<motion.button
key={b.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.08, duration: 0.5 }}
whileHover={{ scale: 1.03, y: -6, transition: { duration: 0.2 } }}
whileTap={{ scale: 0.97 }}
onClick={() => handleButtonClick(b.key)}
className={`group relative rounded-2xl p-4 sm:p-6 shadow-2xl border border-transparent flex flex-col h-full ${isRTL ? "text-right" : "text-left"} focus:outline-none focus:ring-4 focus:ring-amber-200 transition-all duration-300 overflow-hidden bg-white/80 backdrop-blur-sm`}
>
<div className="absolute top-0 right-0 w-20 h-20 sm:w-24 sm:h-24 bg-gradient-to-br from-amber-500/10 to-orange-600/10 rounded-full -mr-12 -mt-12 group-hover:scale-125 transition-transform duration-500" />
<div className="absolute top-0 right-0 w-2 h-0 bg-gradient-to-b from-amber-500 to-orange-600 rounded-r-2xl group-hover:h-full transition-all duration-500" />
<div className="relative z-10">
<div className="flex items-center gap-3 mb-3">
<div className="w-10 h-10 sm:w-14 sm:h-14 bg-gradient-to-br from-amber-500 to-orange-600 rounded-xl flex items-center justify-center text-white text-base sm:text-2xl font-extrabold shadow-xl group-hover:scale-110 group-hover:rotate-6 transition-transform duration-300">
{b.id}
</div>
<h3 className="text-sm sm:text-base font-bold text-gray-800 group-hover:text-amber-700 transition-colors duration-300">{b.title}</h3>
</div>
<p className="text-xs sm:text-sm text-gray-600 mt-auto flex items-center gap-2 group-hover:text-amber-600 transition-colors duration-300">
<span>{t("departmentDetail5.buttons.clickForDetails")}</span>
<svg className="w-4 h-4 sm:w-5 sm:h-5 group-hover:translate-x-2 transition-transform duration-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/>
</svg>
</p>
</div>
</motion.button>
))}
</div>
</motion.div>
)}
</AnimatePresence>
</div>
<div className="absolute bottom-0 left-0 right-0 z-10">
<svg className="w-full h-12 sm:h-16 md:h-24" viewBox="0 0 1200 120" preserveAspectRatio="none">
<path d="M0,0 C300,80 900,80 1200,0 L1200,120 L0,120 Z" fill="#ffffff" opacity="1"/>
</svg>
</div>
</motion.div>
</AnimatePresence>
</div>
</section>
<div className="block md:hidden w-full max-w-7xl mx-auto px-4 sm:px-6 py-6">
<AnimatePresence mode="wait">
{!active && (
<motion.div
key="floating-buttons-mobile"
initial={{ opacity: 0, y: 6 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 6 }}
transition={{ duration: 0.4 }}
>
<div className="grid grid-cols-1 gap-3">
{buttons.map((b, index) => (
<motion.button
key={b.id}
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.05, duration: 0.35 }}
whileHover={{ scale: 1.02 }}
onClick={() => handleButtonClick(b.key)}
className={`group relative rounded-2xl p-3 shadow-md border border-transparent flex items-center gap-3 ${isRTL ? "text-right" : "text-left"} focus:outline-none focus:ring-4 focus:ring-amber-200 transition-all duration-200 overflow-hidden bg-white/90`}
>
<div className="w-10 h-10 bg-gradient-to-br from-amber-500 to-orange-600 rounded-xl flex items-center justify-center text-white text-base font-extrabold shadow">
{b.id}
</div>
<div className="flex-1">
<h3 className="text-sm font-bold text-gray-800">{b.title}</h3>
<p className="text-xs text-gray-600 mt-1">{t("departmentDetail5.buttons.clickForDetails")}</p>
</div>
<svg className="w-5 h-5 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/>
</svg>
</motion.button>
))}
</div>
</motion.div>
)}
</AnimatePresence>
</div>
<section className="max-w-7xl mx-auto px-4 sm:px-6 md:px-6 -mt-6 md:-mt-8 relative z-20">
<AnimatePresence mode="wait">
{!active ? (
<motion.div key="buttons-spacer" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.25 }} className="h-0" />
) : active === "works" ? (
<motion.div key="timeline-view" initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -10 }} transition={{ duration: 0.45 }} className="w-full">
<motion.button initial={{ opacity: 0, x: 20 }} animate={{ opacity: 1, x: 0 }} transition={{ delay: 0.15, duration: 0.45 }} onClick={() => setActive(null)} whileHover={{ x: 8 }} className="inline-flex items-center gap-3 text-amber-600 hover:text-amber-700 font-bold mb-6 sm:mb-8 group text-sm sm:text-base focus:outline-none focus:ring-2 focus:ring-amber-200 rounded-lg px-3 py-2 mr-0 md:-mr-4">
<svg className="w-5 h-5 sm:w-6 sm:h-6 transition-transform group-hover:translate-x-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/>
</svg>
<span>{t("departmentDetail5.buttons.backToMenu")}</span>
</motion.button>
<div style={{ position: 'relative', left: '50%', right: '50%', marginLeft: '-50vw', marginRight: '-50vw', width: '100vw' }}>
<ProjectsTimeline projects={timelineProjects} plain={true} rtl={isRTL} />
</div>
</motion.div>
) : (
<motion.div key="details-view" initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -20 }} transition={{ duration: 0.45 }} className="w-full">
<motion.button initial={{ opacity: 0, x: 20 }} animate={{ opacity: 1, x: 0 }} transition={{ delay: 0.08, duration: 0.45 }} onClick={() => setActive(null)} whileHover={{ x: 8 }} className="inline-flex items-center gap-3 text-amber-600 hover:text-amber-700 font-bold mb-6 sm:mb-8 group text-sm sm:text-base focus:outline-none focus:ring-2 focus:ring-amber-200 rounded-lg px-3 py-2 mr-0 md:-mr-4">
<svg className="w-5 h-5 sm:w-6 sm:h-6 transition-transform group-hover:translate-x-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/>
</svg>
<span>{t("departmentDetail5.buttons.backToMenu")}</span>
</motion.button>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 sm:gap-6">
{displayItems.map((item, index) => (
<motion.div
key={index}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.25 }}
transition={{ delay: index * 0.08, duration: 0.5 }}
className="relative group"
>
<div className={`relative flex items-start gap-3 sm:gap-6 rounded-2xl p-3 sm:p-6 border-r-4 border-amber-400 hover:border-orange-500 hover:shadow-xl transition-all duration-300 bg-white ${isRTL ? "text-right" : "text-left"}`}>
<div className="relative flex-shrink-0">
<motion.div whileHover={{ rotate: 360, scale: 1.08 }} transition={{ duration: 0.6 }} className="w-10 h-10 sm:w-14 sm:h-14 bg-gradient-to-br from-amber-500 to-orange-600 rounded-xl flex items-center justify-center text-white text-base sm:text-2xl font-extrabold shadow-lg group-hover:shadow-2xl transition-shadow duration-300 relative z-10">
{item.icon}
</motion.div>
<div className="absolute inset-0 bg-amber-500 rounded-xl blur-xl opacity-0 group-hover:opacity-30 transition-opacity duration-300" />
</div>
<div className="flex-1 pt-1">
<p className="text-xs sm:text-sm md:text-base text-gray-800 leading-relaxed font-medium group-hover:text-gray-900 transition-colors duration-300">{item.text}</p>
</div>
<motion.div initial={{ opacity: 0, x: -8 }} whileHover={{ opacity: 1, x: 0 }} className="flex-shrink-0 text-amber-500 opacity-0 group-hover:opacity-100 transition-all duration-300">
<svg className="w-4 h-4 sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/>
</svg>
</motion.div>
</div>
</motion.div>
))}
</div>
<motion.div initial={{ opacity: 0, scale: 0.95 }} animate={{ opacity: 1, scale: 1 }} transition={{ delay: 0.6, duration: 0.45 }} className="mt-8 sm:mt-12 pt-6 border-t-2 border-gray-100 text-center">
<div className="inline-flex items-center gap-2 sm:gap-3 text-gray-500">
<div className="w-2 h-2 bg-amber-500 rounded-full animate-pulse" />
<span className="text-xs sm:text-sm font-medium">{t("departmentDetail5.ui.servicesProfessional")}</span>
<div className="w-2 h-2 bg-orange-500 rounded-full animate-pulse" style={{ animationDelay: "0.5s" }} />
</div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
</section>
</div>
);
}