import React, { useState, useEffect, useRef, useCallback } from "react"; import { motion, AnimatePresence } from "framer-motion"; import d19 from "../../../../src/assets/Images/d19.jpeg"; import d27 from "../../../../src/assets/Images/d27.jpeg"; import d28 from "../../../../src/assets/Images/d28.jpeg"; import d29 from "../../../../src/assets/Images/d29.jpeg"; import d30 from "../../../../src/assets/Images/d30.png"; function ProjectsTimeline({ projects, mainTitle = "المشاريع المنفذة", subtitle = "خط زمني شامل للأعمال والإنجازات", plain = false, }) { 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; 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; } .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%); } .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; } .project-text li { margin-bottom:12px; padding-right: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(-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(36px,6vw,80px) 24px; } .timeline-item { margin:0 18px; } .year-circle { width:90px; height:90px; font-size:15px; } .timeline-item.active .year-circle { width:120px; height:120px; font-size:19px; } .project-card { min-width:260px; max-width:300px; padding:20px; } .project-text { font-size:13px; } .scroll-btn { width:48px; height:48px; font-size:20px; } } .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 (
{!plain && (

{mainTitle}

{subtitle}

)}
{projects.map((project, idx) => (
scrollToItem(idx)} role="button" tabIndex={0} onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") scrollToItem(idx); }} >
{project.year}
    {project.items.map((it, i) => (
  • • {it}
  • ))}
))}
); } const defaultProjects = [ { year: "1999-2015", items: [ "تنفيذ محطات معالجة المياه الصناعية لمعامل صهر ودرفلة الحديد الوهيب - العربية - الدولية - حديد للصهر - حديد (1999-2015).", ], }, { year: "2009", items: [ "محطة تحويل 66/20 ك.ف لأعمال درفلة الحديد الوهيب - العربية (2009).", ], }, { year: "2015", items: [ "الإشراف على تنفيذ محطة التحويل 230/66 و66/20 ك.ف لمعامل صهر ودرفلة الحديد (2015).", ], }, { year: "2018", items: [ "تجهيز وتنفيذ شبكات مياه الشرب لـ22 قرية ريف اللاذقية الشمالي - 73 كم (2018).", ], }, { year: "2019", items: [ "أعمال الصيانة وإعادة التأهيل منشأة الفوسفات مرفأ طرطوس (2019).", ], }, { year: "2021", items: [ "دراسة مشروع إعادة تأهيل منجم الملح الصخري في دير الزور (2021).", ], }, { year: "2022", items: [ "دراسة وتنفيذ محطة الضخ والتصفية لسد 16 تشرين (اللاذقية) (2022).", ], }, { year: "2023", items: [ "دراسة وتنفيذ مجموعة الطاقة الشمسية 3.6 ميغا لمطحنة غرين كوست (2023).", ], }, ]; export default function DepartmentDetail6() { const [active, setActive] = useState(null); const cycleImgs = [d28, d27, d29]; const [cycleIndex, setCycleIndex] = useState(0); useEffect(() => { const t = setInterval(() => setCycleIndex((i) => (i + 1) % cycleImgs.length), 3000); return () => clearInterval(t); }, []); const buttons = [ { id: 1, title: "خدمات القسم", key: "expertise" }, { id: 3, title: "الاعمال المنفذه", key: "works", img: d30 }, ]; const cardGroups = [ { title: "1- محطات المعالجة وتصفية المياه", items: [ "تنفيذ محطات تصفية ومعالجة وضخ المياه الصالحة للشرب والاستخدام.", "تنفيذ محطات معالجة المياه الصناعية وفق المتطلبات الفنية والتشغيلية.", "الإشراف على التشغيل التجريبي ورفع كفاءة الأداء التشغيلي للمحطات.", "الالتزام بالمعايير البيئية ومعايير الجودة والسلامة المهنية المعتمدة.", ], }, { title: "2- محطات الطاقة الكهروضوئية", items: [ "دراسة وتصميم وتنفيذ مشاريع الطاقة البديلة (الكهروضوئية / الريحية).", "تنفيذ المحطات الكهروضوئية وأنظمة الطاقة الشمسية.", "تصميم وتنفيذ منظومات الكهرباء والتحكم والمحولات الكهربائية.", "ربط أنظمة الطاقة الكهربائية مع أنظمة الطاقة البديلة.", "الإشراف على التشغيل والصيانة الدورية للمنظومات الطاقية.", ], }, { title: "3- منشآت الفوسفات", items: [ "إعادة تأهيل خطوط تفريغ وتعبئة الفوسفات من مرحلة تفريغ القطارات وحتى تحميل الفوسفت على البواخر.", "تنفيذ أعمال الصيانة الميكانيكية والكهربائية والتحكم وأعمال اللحام والمعالجة المعدنية لمنظومات التفريغ والنقل والتعبئة.", "فحص وتقييم الحالة الفنية للمعدات والمنشآت، وإعادة ضبط المنظومات التشغيلية ورفع الجاهزية والكفاءة التشغيلية.", "تطبيق متطلبات السلامة خلال أعمال التنفيذ والتشغيل.", ], }, ]; const heroImage = active === "expertise" ? cycleImgs[cycleIndex] : active === "works" ? d30 : d19; const handleButtonClick = (key) => { setActive((prev) => (prev === key ? null : key)); }; return (
مرافق ومشروعات استراتيجية
{active === "expertise" ? (
خدمات القسم

خدمات القسم

الاطّلاع على البطاقات أدناه للحصول على تفاصيل كل خدمة.

) : active === "works" ? (
الاعمال المنفذة

الاعمال المنفذة

عرض مشروعاتنا وخط الزمن الخاص بالأعمال المنفذة.

) : (

قسم المشاريع الاستراتيجية

)}
{!active && (
{buttons.map((b, index) => ( handleButtonClick(b.key)} className="group relative rounded-2xl p-4 sm:p-6 shadow-2xl border border-transparent flex flex-col h-full text-right focus:outline-none focus:ring-4 focus:ring-amber-200 transition-all duration-300 overflow-hidden bg-white/80 backdrop-blur-sm" >
{b.id}

{b.title}

انقر للاطّلاع على التفاصيل

))}
)}
{!active ? ( ) : active === "works" ? ( 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"> العودة للقائمة الرئيسية
) : ( 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"> العودة للقائمة الرئيسية
{cardGroups.map((group, gIndex) => (

{group.title}

{group.items.map((text, idx) => (

{text}

))}
))}
خدمات احترافية متكاملة
)}
); }