This commit is contained in:
Rahaf
2026-01-14 13:08:05 +03:00
7 changed files with 2643 additions and 294 deletions

View File

@ -1,15 +1,13 @@
import React, { useState, useEffect, useRef, useCallback } from "react"; import React, { useState, useEffect, useRef, useCallback } from "react";
import { motion, AnimatePresence } from "framer-motion"; import { motion, AnimatePresence } from "framer-motion";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import "../../../../src/i18n"; // احتفظت بالاستيراد كما طلبت import "../../../../src/i18n";
// استيراد الصور كما كانت في واجهتك
import d1 from "../../../../src/assets/Images/d1.jpeg"; import d1 from "../../../../src/assets/Images/d1.jpeg";
import d2 from "../../../../src/assets/Images/d2.jpeg"; import d2 from "../../../../src/assets/Images/d2.jpeg";
import d3 from "../../../../src/assets/Images/d3.jpeg"; import d3 from "../../../../src/assets/Images/d3.jpeg";
import d4 from "../../../../src/assets/Images/d4.jpeg"; import d4 from "../../../../src/assets/Images/d4.jpeg";
/* -------------------- ProjectsTimeline (مضمن داخل نفس الملف كما في واجهتك) -------------------- */
function ProjectsTimeline({ function ProjectsTimeline({
projects, projects,
mainTitle = "المشاريع المنفذة", mainTitle = "المشاريع المنفذة",
@ -130,7 +128,11 @@ function ProjectsTimeline({
const scrollLeft = scrollContainer.scrollLeft; const scrollLeft = scrollContainer.scrollLeft;
const targetScroll = const targetScroll =
scrollLeft + itemRect.left - containerRect.left - containerRect.width / 2 + itemRect.width / 2; scrollLeft +
itemRect.left -
containerRect.left -
containerRect.width / 2 +
itemRect.width / 2;
scrollContainer.scrollTo({ left: targetScroll, behavior: "smooth" }); scrollContainer.scrollTo({ left: targetScroll, behavior: "smooth" });
setActiveItem(index); setActiveItem(index);
@ -187,7 +189,8 @@ function ProjectsTimeline({
return () => { return () => {
clearTimeout(t); clearTimeout(t);
if (scrollContainer) scrollContainer.removeEventListener("scroll", onScroll); if (scrollContainer)
scrollContainer.removeEventListener("scroll", onScroll);
window.removeEventListener("resize", onResize); window.removeEventListener("resize", onResize);
}; };
}, [itemsRefs, drawCurvedLines, setActiveItem]); }, [itemsRefs, drawCurvedLines, setActiveItem]);
@ -238,25 +241,64 @@ function ProjectsTimeline({
.projects-timeline-root.plain-bleed .project-card { max-width:420px; } .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%)" }; const mainStyle = plain
? { background: "#ffffff", paddingBottom: 0 }
: {
background:
"linear-gradient(135deg, var(--bg-start) 0%, var(--bg-mid) 30%, var(--bg-end) 60%)",
};
return ( return (
<div className={`projects-timeline-root w-full h-full ${plain ? "plain-bleed" : ""}`}> <div
className={`projects-timeline-root w-full h-full ${
plain ? "plain-bleed" : ""
}`}
>
<style>{css}</style> <style>{css}</style>
<main className="w-full h-full overflow-hidden" style={mainStyle}> <main className="w-full h-full overflow-hidden" style={mainStyle}>
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
{!plain && ( {!plain && (
<header className="text-center py-8 px-4"> <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)" }}> <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} {mainTitle}
</h1> </h1>
<p id="subtitle" className={`${plain ? "text-base text-gray-700" : "text-xl text-white opacity-90"}`}>{subtitle}</p> <p
id="subtitle"
className={`${
plain
? "text-base text-gray-700"
: "text-xl text-white opacity-90"
}`}
>
{subtitle}
</p>
</header> </header>
)} )}
<div className="flex-1 relative"> <div className="flex-1 relative">
<div className="timeline-scroll h-full" id="timeline-scroll" ref={scrollRef} aria-label="خط زمني قابل للتمرير"> <div
<div className="timeline-wrapper" id="timeline-wrapper" ref={wrapperRef}> className="timeline-scroll h-full"
id="timeline-scroll"
ref={scrollRef}
aria-label="خط زمني قابل للتمرير"
>
<div
className="timeline-wrapper"
id="timeline-wrapper"
ref={wrapperRef}
>
<svg className="svg-container" id="timeline-svg" ref={svgRef} /> <svg className="svg-container" id="timeline-svg" ref={svgRef} />
{projects.map((project, idx) => ( {projects.map((project, idx) => (
<div <div
@ -285,8 +327,24 @@ function ProjectsTimeline({
</div> </div>
<div className="scroll-indicator"> <div className="scroll-indicator">
<button className="scroll-btn" aria-label="السابق" onClick={onPrev} disabled={currentIndex === 0} title="السابق"></button> <button
<button className="scroll-btn" aria-label="التالي" onClick={onNext} disabled={currentIndex === projects.length - 1} title="التالي"></button> className="scroll-btn"
aria-label="السابق"
onClick={onPrev}
disabled={currentIndex === 0}
title="السابق"
>
</button>
<button
className="scroll-btn"
aria-label="التالي"
onClick={onNext}
disabled={currentIndex === projects.length - 1}
title="التالي"
>
</button>
</div> </div>
</div> </div>
</div> </div>
@ -295,8 +353,6 @@ function ProjectsTimeline({
); );
} }
/* -------------------- نهاية ProjectsTimeline -------------------- */
const defaultProjects = [ const defaultProjects = [
{ {
year: "1999-2015", year: "1999-2015",
@ -308,7 +364,10 @@ const defaultProjects = [
], ],
}, },
{ year: "2001", items: ["أعمال تشغيل وصيانة الدورة لمعمل الوهيب ستوك إير"] }, { year: "2001", items: ["أعمال تشغيل وصيانة الدورة لمعمل الوهيب ستوك إير"] },
{ year: "2002", items: ["أعمال تشغيل وصيانة الدورة لمعمل العربية لدرفلة إير"] }, {
year: "2002",
items: ["أعمال تشغيل وصيانة الدورة لمعمل العربية لدرفلة إير"],
},
{ year: "2004", items: ["أعمال متنوعة في مجال الدرفلة والتصنيع"] }, { year: "2004", items: ["أعمال متنوعة في مجال الدرفلة والتصنيع"] },
{ {
year: "2016", year: "2016",
@ -317,7 +376,10 @@ const defaultProjects = [
"أي أم، التايتيك - التروت، تصميم وتنفيذ", "أي أم، التايتيك - التروت، تصميم وتنفيذ",
], ],
}, },
{ year: "2016-2017", items: ["التدريب العالمي 600 طن/يوم", "التدريب للصناعات الغذائية"] }, {
year: "2016-2017",
items: ["التدريب العالمي 600 طن/يوم", "التدريب للصناعات الغذائية"],
},
{ year: "2017", items: ["دراسة تأهيلية معمل الشمس (العسافي - حمص)"] }, { year: "2017", items: ["دراسة تأهيلية معمل الشمس (العسافي - حمص)"] },
{ {
year: "2019", year: "2019",
@ -327,8 +389,17 @@ const defaultProjects = [
], ],
}, },
{ year: "2020", items: ["استكمال دراسة تأهيلية للصم وقياس الشمس"] }, { year: "2020", items: ["استكمال دراسة تأهيلية للصم وقياس الشمس"] },
{ year: "2021", items: ["منشأ تيسير لمعمل المتحدة، تصميم الاسور - أبو الشامات"] }, {
{ year: "2022", items: ["استكمال منشأ تيسير لمعمل المتحدة", "معمل المثنى للتصنيع السريع - طرطوس"] }, year: "2021",
items: ["منشأ تيسير لمعمل المتحدة، تصميم الاسور - أبو الشامات"],
},
{
year: "2022",
items: [
"استكمال منشأ تيسير لمعمل المتحدة",
"معمل المثنى للتصنيع السريع - طرطوس",
],
},
{ year: "2023", items: ["مشاريع متنوعة في مجال التصنيع والدرفلة"] }, { year: "2023", items: ["مشاريع متنوعة في مجال التصنيع والدرفلة"] },
]; ];
@ -342,7 +413,12 @@ export default function DepartmentDetail() {
{ id: 3, title: t("department.buttons.works"), key: "works" }, { id: 3, title: t("department.buttons.works"), key: "works" },
]; ];
const expertiseItems = t("department.expertiseItems", { returnObjects: true }) || [ const expertiseItemsRaw = t("department.expertiseItems", {
returnObjects: true,
});
const expertiseItems = Array.isArray(expertiseItemsRaw)
? expertiseItemsRaw
: [
"دراسات الجدوى الاقتصادية وتحليل الربحية والمخاطر للمشاريع الصناعية والهندسية", "دراسات الجدوى الاقتصادية وتحليل الربحية والمخاطر للمشاريع الصناعية والهندسية",
"الدراسات الهندسية الأولية والنهائية والتفصيلية", "الدراسات الهندسية الأولية والنهائية والتفصيلية",
"تصميم المخططات التنفيذية", "تصميم المخططات التنفيذية",
@ -352,7 +428,12 @@ export default function DepartmentDetail() {
"الإشراف على التشغيل التجريبي وتدريب الكوادر الفنية", "الإشراف على التشغيل التجريبي وتدريب الكوادر الفنية",
]; ];
const servicesItems = t("department.servicesItems", { returnObjects: true }) || [ const servicesItemsRaw = t("department.servicesItems", {
returnObjects: true,
});
const servicesItems = Array.isArray(servicesItemsRaw)
? servicesItemsRaw
: [
"الصيانة الدورية والوقائية.", "الصيانة الدورية والوقائية.",
"الصيانة الطارئة ومعالجة الأعطال.", "الصيانة الطارئة ومعالجة الأعطال.",
"إعادة التأهيل والتحديث الفني للمنشآت.", "إعادة التأهيل والتحديث الفني للمنشآت.",
@ -361,10 +442,18 @@ export default function DepartmentDetail() {
"رفع كفاءة التشغيل وتقليل تكاليف الأعطال", "رفع كفاءة التشغيل وتقليل تكاليف الأعطال",
]; ];
const defaultProjectsTranslated = t("department.defaultProjects", { returnObjects: true }) || defaultProjects; const defaultProjectsTranslated =
t("department.defaultProjects", { returnObjects: true }) || defaultProjects;
const displayItems = active === "services" ? servicesItems : expertiseItems; const displayItems = active === "services" ? servicesItems : expertiseItems;
const heroImage = active === "expertise" ? d2 : active === "services" ? d3 : active === "works" ? d4 : d1; const heroImage =
active === "expertise"
? d2
: active === "services"
? d3
: active === "works"
? d4
: d1;
const handleButtonClick = (key) => { const handleButtonClick = (key) => {
setActive((prev) => (prev === key ? null : key)); setActive((prev) => (prev === key ? null : key));
@ -400,12 +489,21 @@ export default function DepartmentDetail() {
<div className="max-w-7xl mx-auto px-4 sm:px-6 w-full"> <div className="max-w-7xl mx-auto px-4 sm:px-6 w-full">
<AnimatePresence mode="wait"> <AnimatePresence mode="wait">
{active === "expertise" ? ( {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"> <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"> <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("department.hero.expertiseBadge") || "اختصاص القسم"} {t("department.hero.expertiseBadge") ||
"اختصاص القسم"}
</div> </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"> <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("department.hero.expertiseTitle") || "حلول متكاملة للمنشآت الصناعية"} {t("department.hero.expertiseTitle") ||
"حلول متكاملة للمنشآت الصناعية"}
</h2> </h2>
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg"> <p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">
{t("department.hero.expertiseSubtitle") || {t("department.hero.expertiseSubtitle") ||
@ -413,19 +511,35 @@ export default function DepartmentDetail() {
</p> </p>
</motion.div> </motion.div>
) : active === "services" ? ( ) : active === "services" ? (
<motion.div key="services-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"> <motion.div
key="services-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"> <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("department.hero.servicesBadge") || "خدمات القسم"} {t("department.hero.servicesBadge") || "خدمات القسم"}
</div> </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"> <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("department.hero.servicesTitle") || "خدمات الصيانة للمنشآت وخطوط الإنتاج"} {t("department.hero.servicesTitle") ||
"خدمات الصيانة للمنشآت وخطوط الإنتاج"}
</h2> </h2>
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg"> <p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">
{t("department.hero.servicesSubtitle") || "يتضمن هذا القسم خدمات الصيانة الشاملة والدورية للمنشآت الصناعية وخطوط الانتاج، وتشمل:"} {t("department.hero.servicesSubtitle") ||
"يتضمن هذا القسم خدمات الصيانة الشاملة والدورية للمنشآت الصناعية وخطوط الانتاج، وتشمل:"}
</p> </p>
</motion.div> </motion.div>
) : active === "works" ? ( ) : 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"> <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"> <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("department.hero.worksBadge") || "الأعمال المنفذة"} {t("department.hero.worksBadge") || "الأعمال المنفذة"}
</div> </div>
@ -433,13 +547,22 @@ export default function DepartmentDetail() {
{t("department.hero.worksTitle") || "الأعمال المنفذة"} {t("department.hero.worksTitle") || "الأعمال المنفذة"}
</h2> </h2>
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg"> <p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">
{t("department.hero.worksSubtitle") || "عرض مشروعاتنا وخط الزمن الخاص بالأعمال المنفذة."} {t("department.hero.worksSubtitle") ||
"عرض مشروعاتنا وخط الزمن الخاص بالأعمال المنفذة."}
</p> </p>
</motion.div> </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"> <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"> <h2 className="text-xl sm:text-2xl md:text-4xl lg:text-5xl font-extrabold drop-shadow-2xl leading-tight">
{t("department.sectionTitle") || "قسم إنشاء وصيانة المنشآت الصناعية وخطوط الإنتاج"} {t("department.sectionTitle") ||
"قسم إنشاء وصيانة المنشآت الصناعية وخطوط الإنتاج"}
</h2> </h2>
</motion.div> </motion.div>
)} )}
@ -447,7 +570,10 @@ export default function DepartmentDetail() {
</div> </div>
</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 }}> <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> <AnimatePresence>
{!active && ( {!active && (
<motion.div <motion.div
@ -465,7 +591,11 @@ export default function DepartmentDetail() {
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.08, duration: 0.5 }} transition={{ delay: index * 0.08, duration: 0.5 }}
whileHover={{ scale: 1.03, y: -6, transition: { duration: 0.2 } }} whileHover={{
scale: 1.03,
y: -6,
transition: { duration: 0.2 },
}}
whileTap={{ scale: 0.97 }} whileTap={{ scale: 0.97 }}
onClick={() => handleButtonClick(b.key)} onClick={() => 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" 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"
@ -477,12 +607,24 @@ export default function DepartmentDetail() {
<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"> <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} {b.id}
</div> </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> <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> </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"> <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("department.clickForDetails")}</span> <span>{t("department.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"> <svg
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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> </svg>
</p> </p>
</div> </div>
@ -495,8 +637,16 @@ export default function DepartmentDetail() {
</div> </div>
<div className="absolute bottom-0 left-0 right-0 z-10"> <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"> <svg
<path d="M0,0 C300,80 900,80 1200,0 L1200,120 L0,120 Z" fill="#ffffff" opacity="1"/> 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> </svg>
</div> </div>
</motion.div> </motion.div>
@ -529,11 +679,25 @@ export default function DepartmentDetail() {
{b.id} {b.id}
</div> </div>
<div className="flex-1"> <div className="flex-1">
<h3 className="text-sm font-bold text-gray-800">{b.title}</h3> <h3 className="text-sm font-bold text-gray-800">
<p className="text-xs text-gray-600 mt-1">{t("department.clickForDetails")}</p> {b.title}
</h3>
<p className="text-xs text-gray-600 mt-1">
{t("department.clickForDetails")}
</p>
</div> </div>
<svg className="w-5 h-5 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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> </svg>
</motion.button> </motion.button>
))} ))}
@ -546,25 +710,92 @@ export default function DepartmentDetail() {
<section className="max-w-7xl mx-auto px-4 sm:px-6 md:px-6 -mt-6 md:-mt-8 relative z-20"> <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"> <AnimatePresence mode="wait">
{!active ? ( {!active ? (
<motion.div key="buttons-spacer" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.25 }} className="h-0" /> <motion.div
key="buttons-spacer"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.25 }}
className="h-0"
/>
) : active === "works" ? ( ) : 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.div
<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"> key="timeline-view"
<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"> initial={{ opacity: 0, y: 20 }}
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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> </svg>
<span>{t("department.backToMenu")}</span> <span>{t("department.backToMenu")}</span>
</motion.button> </motion.button>
<div style={{ position: 'relative', left: '50%', right: '50%', marginLeft: '-50vw', marginRight: '-50vw', width: '100vw' }}> <div
<ProjectsTimeline projects={defaultProjectsTranslated} plain={true} /> style={{
position: "relative",
left: "50%",
right: "50%",
marginLeft: "-50vw",
marginRight: "-50vw",
width: "100vw",
}}
>
<ProjectsTimeline
projects={defaultProjectsTranslated}
plain={true}
/>
</div> </div>
</motion.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.div
<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"> key="details-view"
<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"> initial={{ opacity: 0, y: 20 }}
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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> </svg>
<span>{t("department.backToMenu")}</span> <span>{t("department.backToMenu")}</span>
</motion.button> </motion.button>
@ -581,19 +812,51 @@ export default function DepartmentDetail() {
> >
<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"> <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">
<div className="relative flex-shrink-0"> <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 shadow-lg group-hover:shadow-2xl transition-shadow duration-300 relative z-10"> <motion.div
<svg className="w-6 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> 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 shadow-lg group-hover:shadow-2xl transition-shadow duration-300 relative z-10"
>
<svg
className="w-6 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> </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 className="absolute inset-0 bg-amber-500 rounded-xl blur-xl opacity-0 group-hover:opacity-30 transition-opacity duration-300" />
</div> </div>
<div className="flex-1 pt-1"> <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">{text}</p> <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">
{text}
</p>
</div> </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"> <motion.div
<svg className="w-4 h-4 sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> initial={{ opacity: 0, x: -8 }}
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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> </svg>
</motion.div> </motion.div>
</div> </div>
@ -601,11 +864,21 @@ export default function DepartmentDetail() {
))} ))}
</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"> <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="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" /> <div className="w-2 h-2 bg-amber-500 rounded-full animate-pulse" />
<span className="text-xs sm:text-sm font-medium">Professional integrated services</span> <span className="text-xs sm:text-sm font-medium">
<div className="w-2 h-2 bg-orange-500 rounded-full animate-pulse" style={{ animationDelay: "0.5s" }} /> Professional integrated services
</span>
<div
className="w-2 h-2 bg-orange-500 rounded-full animate-pulse"
style={{ animationDelay: "0.5s" }}
/>
</div> </div>
</motion.div> </motion.div>
</motion.div> </motion.div>

View File

@ -15,7 +15,7 @@ function ProjectsTimeline({
dir = "rtl", dir = "rtl",
scrollLabel = "خط زمني قابل للتمرير", scrollLabel = "خط زمني قابل للتمرير",
prevLabel = "السابق", prevLabel = "السابق",
nextLabel = "التالي" nextLabel = "التالي",
}) { }) {
const wrapperRef = useRef(null); const wrapperRef = useRef(null);
const scrollRef = useRef(null); const scrollRef = useRef(null);
@ -131,7 +131,11 @@ function ProjectsTimeline({
const scrollLeft = scrollContainer.scrollLeft; const scrollLeft = scrollContainer.scrollLeft;
const targetScroll = const targetScroll =
scrollLeft + itemRect.left - containerRect.left - containerRect.width / 2 + itemRect.width / 2; scrollLeft +
itemRect.left -
containerRect.left -
containerRect.width / 2 +
itemRect.width / 2;
scrollContainer.scrollTo({ left: targetScroll, behavior: "smooth" }); scrollContainer.scrollTo({ left: targetScroll, behavior: "smooth" });
setActiveItem(index); setActiveItem(index);
@ -188,7 +192,8 @@ function ProjectsTimeline({
return () => { return () => {
clearTimeout(t); clearTimeout(t);
if (scrollContainer) scrollContainer.removeEventListener("scroll", onScroll); if (scrollContainer)
scrollContainer.removeEventListener("scroll", onScroll);
window.removeEventListener("resize", onResize); window.removeEventListener("resize", onResize);
}; };
}, [itemsRefs, drawCurvedLines, setActiveItem]); }, [itemsRefs, drawCurvedLines, setActiveItem]);
@ -253,25 +258,65 @@ function ProjectsTimeline({
.projects-timeline-root.plain-bleed .project-card { max-width:420px; } .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%)" }; const mainStyle = plain
? { background: "#ffffff", paddingBottom: 0 }
: {
background:
"linear-gradient(135deg, var(--bg-start) 0%, var(--bg-mid) 30%, var(--bg-end) 60%)",
};
return ( return (
<div className={`projects-timeline-root w-full h-full ${plain ? "plain-bleed" : ""}`} dir={dir}> <div
className={`projects-timeline-root w-full h-full ${
plain ? "plain-bleed" : ""
}`}
dir={dir}
>
<style>{css}</style> <style>{css}</style>
<main className="w-full h-full overflow-hidden" style={mainStyle}> <main className="w-full h-full overflow-hidden" style={mainStyle}>
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
{!plain && ( {!plain && (
<header className="text-center py-8 px-4"> <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)" }}> <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} {mainTitle}
</h1> </h1>
<p id="subtitle" className={`${plain ? "text-base text-gray-700" : "text-xl text-white opacity-90"}`}>{subtitle}</p> <p
id="subtitle"
className={`${
plain
? "text-base text-gray-700"
: "text-xl text-white opacity-90"
}`}
>
{subtitle}
</p>
</header> </header>
)} )}
<div className="flex-1 relative"> <div className="flex-1 relative">
<div className="timeline-scroll h-full" id="timeline-scroll" ref={scrollRef} aria-label={scrollLabel}> <div
<div className="timeline-wrapper" id="timeline-wrapper" ref={wrapperRef}> className="timeline-scroll h-full"
id="timeline-scroll"
ref={scrollRef}
aria-label={scrollLabel}
>
<div
className="timeline-wrapper"
id="timeline-wrapper"
ref={wrapperRef}
>
<svg className="svg-container" id="timeline-svg" ref={svgRef} /> <svg className="svg-container" id="timeline-svg" ref={svgRef} />
{projects.map((project, idx) => ( {projects.map((project, idx) => (
<div <div
@ -300,8 +345,24 @@ function ProjectsTimeline({
</div> </div>
<div className="scroll-indicator"> <div className="scroll-indicator">
<button className="scroll-btn" aria-label={prevLabel} onClick={onPrev} disabled={currentIndex === 0} title={prevLabel}></button> <button
<button className="scroll-btn" aria-label={nextLabel} onClick={onNext} disabled={currentIndex === projects.length - 1} title={nextLabel}></button> className="scroll-btn"
aria-label={prevLabel}
onClick={onPrev}
disabled={currentIndex === 0}
title={prevLabel}
>
</button>
<button
className="scroll-btn"
aria-label={nextLabel}
onClick={onNext}
disabled={currentIndex === projects.length - 1}
title={nextLabel}
>
</button>
</div> </div>
</div> </div>
</div> </div>
@ -319,19 +380,53 @@ export default function DepartmentDetail6() {
const cycleImgs = [d28, d27, d29]; const cycleImgs = [d28, d27, d29];
const [cycleIndex, setCycleIndex] = useState(0); const [cycleIndex, setCycleIndex] = useState(0);
useEffect(() => { useEffect(() => {
const tInterval = setInterval(() => setCycleIndex((i) => (i + 1) % cycleImgs.length), 3000); const tInterval = setInterval(
() => setCycleIndex((i) => (i + 1) % cycleImgs.length),
3000
);
return () => clearInterval(tInterval); return () => clearInterval(tInterval);
}, []); }, []);
// buttons from translations (array) // buttons from translations (array)
const buttons = t("departmentDetail6.buttons", { returnObjects: true }); const buttons = [
{ id: 1, title: t("departmentDetail6.buttons.1"), key: "expertise" },
{ id: 3, title: t("departmentDetail6.buttons.3"), key: "works" },
];
// card groups from translations // card groups from translations
const cardGroups = t("departmentDetail6.cardGroups", { returnObjects: true }); const cardGroupsRaw = t("departmentDetail6.cardGroups", {
returnObjects: true,
});
const projectsTimeline = t("departmentDetail6.projectsTimeline.defaultProjects", { returnObjects: true }); const expertiseItemsRaw = t("departmentDetail6.expertiseItems", {
returnObjects: true,
});
const validExpertiseItems = Array.isArray(expertiseItemsRaw)
? expertiseItemsRaw
: [];
const heroImage = active === "expertise" ? cycleImgs[cycleIndex] : active === "works" ? d30 : d19; const cardGroups = Array.isArray(cardGroupsRaw)
? cardGroupsRaw
: [
{
title:
t("departmentDetail6.hero.expertiseBadge") ||
"Department Expertise",
items: validExpertiseItems,
},
];
const projectsTimeline = t(
"departmentDetail6.projectsTimeline.defaultProjects",
{ returnObjects: true }
);
const heroImage =
active === "expertise"
? cycleImgs[cycleIndex]
: active === "works"
? d30
: d19;
const handleButtonClick = (key) => { const handleButtonClick = (key) => {
setActive((prev) => (prev === key ? null : key)); setActive((prev) => (prev === key ? null : key));
@ -344,7 +439,10 @@ export default function DepartmentDetail6() {
const backToMenu = t("departmentDetail6.backToMenu"); const backToMenu = t("departmentDetail6.backToMenu");
return ( return (
<div dir={isRTL ? "rtl" : "ltr"} className="w-full min-h-screen bg-white pb-12"> <div
dir={isRTL ? "rtl" : "ltr"}
className="w-full min-h-screen bg-white pb-12"
>
<section className="relative"> <section className="relative">
<div className="w-full"> <div className="w-full">
<AnimatePresence mode="wait"> <AnimatePresence mode="wait">
@ -354,7 +452,11 @@ export default function DepartmentDetail6() {
animate={{ opacity: 1, scale: 1 }} animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.98 }} exit={{ opacity: 0, scale: 0.98 }}
transition={{ duration: 0.6 }} transition={{ duration: 0.6 }}
className={`relative ${active ? 'h-80 sm:h-96 md:h-[540px] lg:h-[680px]' : 'h-72 sm:h-80 md:h-[480px] lg:h-[580px]'} overflow-visible`} className={`relative ${
active
? "h-80 sm:h-96 md:h-[540px] lg:h-[680px]"
: "h-72 sm:h-80 md:h-[480px] lg:h-[580px]"
} overflow-visible`}
> >
<img <img
src={heroImage} src={heroImage}
@ -373,27 +475,71 @@ export default function DepartmentDetail6() {
<div className="max-w-7xl mx-auto px-4 sm:px-6 w-full"> <div className="max-w-7xl mx-auto px-4 sm:px-6 w-full">
<AnimatePresence mode="wait"> <AnimatePresence mode="wait">
{active === "expertise" ? ( {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 ${isRTL ? 'text-right' : 'text-left'}`}> <motion.div
<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("departmentDetail6.hero.expertiseBadge")}</div> key="expertise-title"
<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("departmentDetail6.hero.expertiseTitle")}</h2> initial={{ opacity: 0, x: -50 }}
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">{t("departmentDetail6.hero.expertiseSubtitle")}</p> animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: 50 }}
transition={{ duration: 0.5 }}
className={`text-white max-w-4xl ${
isRTL ? "text-right" : "text-left"
}`}
>
<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("departmentDetail6.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("departmentDetail6.hero.expertiseTitle")}
</h2>
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">
{t("departmentDetail6.hero.expertiseSubtitle")}
</p>
</motion.div> </motion.div>
) : active === "works" ? ( ) : 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 ${isRTL ? 'text-right' : 'text-left'}`}> <motion.div
<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("departmentDetail6.hero.worksBadge")}</div> key="works-title"
<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("departmentDetail6.hero.worksTitle")}</h2> initial={{ opacity: 0, x: -50 }}
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">{t("departmentDetail6.hero.worksSubtitle")}</p> animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: 50 }}
transition={{ duration: 0.5 }}
className={`text-white max-w-4xl ${
isRTL ? "text-right" : "text-left"
}`}
>
<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("departmentDetail6.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("departmentDetail6.hero.worksTitle")}
</h2>
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">
{t("departmentDetail6.hero.worksSubtitle")}
</p>
</motion.div> </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 ${isRTL ? 'text-right' : 'text-left'}`}> <motion.div
<h2 className="text-xl sm:text-2xl md:text-4xl lg:text-5xl font-extrabold drop-shadow-2xl leading-tight">{t("departmentDetail6.hero.defaultTitle")}</h2> 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 ${
isRTL ? "text-right" : "text-left"
}`}
>
<h2 className="text-xl sm:text-2xl md:text-4xl lg:text-5xl font-extrabold drop-shadow-2xl leading-tight">
{t("departmentDetail6.hero.defaultTitle")}
</h2>
</motion.div> </motion.div>
)} )}
</AnimatePresence> </AnimatePresence>
</div> </div>
</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 }}> <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> <AnimatePresence>
{!active && ( {!active && (
<motion.div <motion.div
@ -411,10 +557,16 @@ export default function DepartmentDetail6() {
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.08, duration: 0.5 }} transition={{ delay: index * 0.08, duration: 0.5 }}
whileHover={{ scale: 1.03, y: -6, transition: { duration: 0.2 } }} whileHover={{
scale: 1.03,
y: -6,
transition: { duration: 0.2 },
}}
whileTap={{ scale: 0.97 }} whileTap={{ scale: 0.97 }}
onClick={() => handleButtonClick(b.key)} 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`} 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 to-orange-600 rounded-full -mr-12 -mt-12 group-hover:scale-125 transition-transform duration-500" /> <div className="absolute top-0 right-0 w-20 h-20 sm:w-24 sm:h-24 bg-gradient-to-br from-amber-500 to-orange-600 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="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" />
@ -424,12 +576,24 @@ export default function DepartmentDetail6() {
<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"> <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} {b.id}
</div> </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> <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> </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"> <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>{ui.clickToView}</span> <span>{ui.clickToView}</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"> <svg
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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> </svg>
</p> </p>
</div> </div>
@ -442,8 +606,16 @@ export default function DepartmentDetail6() {
</div> </div>
<div className="absolute bottom-0 left-0 right-0 z-10"> <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"> <svg
<path d="M0,0 C300,80 900,80 1200,0 L1200,120 L0,120 Z" fill="#ffffff" opacity="1"/> 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> </svg>
</div> </div>
</motion.div> </motion.div>
@ -470,17 +642,33 @@ export default function DepartmentDetail6() {
transition={{ delay: index * 0.05, duration: 0.35 }} transition={{ delay: index * 0.05, duration: 0.35 }}
whileHover={{ scale: 1.02 }} whileHover={{ scale: 1.02 }}
onClick={() => handleButtonClick(b.key)} 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`} 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"> <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} {b.id}
</div> </div>
<div className="flex-1"> <div className="flex-1">
<h3 className="text-sm font-bold text-gray-800">{b.title}</h3> <h3 className="text-sm font-bold text-gray-800">
<p className="text-xs text-gray-600 mt-1">{ui.clickToView}</p> {b.title}
</h3>
<p className="text-xs text-gray-600 mt-1">
{ui.clickToView}
</p>
</div> </div>
<svg className="w-5 h-5 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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> </svg>
</motion.button> </motion.button>
))} ))}
@ -493,21 +681,63 @@ export default function DepartmentDetail6() {
<section className="max-w-7xl mx-auto px-4 sm:px-6 md:px-6 -mt-6 md:-mt-8 relative z-20"> <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"> <AnimatePresence mode="wait">
{!active ? ( {!active ? (
<motion.div key="buttons-spacer" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.25 }} className="h-0" /> <motion.div
key="buttons-spacer"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.25 }}
className="h-0"
/>
) : active === "works" ? ( ) : 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.div
<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 ${isRTL ? 'mr-0 md:-mr-4' : 'ml-0 md:-ml-4'}`}> key="timeline-view"
<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"> initial={{ opacity: 0, y: 20 }}
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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 ${
isRTL ? "mr-0 md:-mr-4" : "ml-0 md:-ml-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> </svg>
<span>{backToMenu}</span> <span>{backToMenu}</span>
</motion.button> </motion.button>
<div style={{ position: 'relative', left: '50%', right: '50%', marginLeft: '-50vw', marginRight: '-50vw', width: '100vw' }}> <div
style={{
position: "relative",
left: "50%",
right: "50%",
marginLeft: "-50vw",
marginRight: "-50vw",
width: "100vw",
}}
>
<ProjectsTimeline <ProjectsTimeline
projects={projectsTimeline} projects={projectsTimeline}
plain={true} plain={true}
dir={isRTL ? 'rtl' : 'ltr'} dir={isRTL ? "rtl" : "ltr"}
mainTitle={t("departmentDetail6.hero.worksTitle")} mainTitle={t("departmentDetail6.hero.worksTitle")}
subtitle={t("departmentDetail6.hero.worksSubtitle")} subtitle={t("departmentDetail6.hero.worksSubtitle")}
scrollLabel={t("departmentDetail6.scroll.ariaLabel")} scrollLabel={t("departmentDetail6.scroll.ariaLabel")}
@ -517,36 +747,102 @@ export default function DepartmentDetail6() {
</div> </div>
</motion.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.div
<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 ${isRTL ? 'mr-0 md:-mr-4' : 'ml-0 md:-ml-4'}`}> key="details-view"
<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"> initial={{ opacity: 0, y: 20 }}
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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 ${
isRTL ? "mr-0 md:-mr-4" : "ml-0 md:-ml-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> </svg>
<span>{backToMenu}</span> <span>{backToMenu}</span>
</motion.button> </motion.button>
<div className="grid grid-cols-1 gap-6"> <div className="grid grid-cols-1 gap-6">
{cardGroups.map((group, gIndex) => ( {cardGroups.map((group, gIndex) => (
<div key={gIndex} className="bg-white rounded-2xl p-4 sm:p-6 shadow-lg border border-gray-100"> <div
<h3 className="text-lg font-bold text-gray-800 mb-3">{group.title}</h3> key={gIndex}
className="bg-white rounded-2xl p-4 sm:p-6 shadow-lg border border-gray-100"
>
<h3 className="text-lg font-bold text-gray-800 mb-3">
{group.title}
</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{group.items.map((text, idx) => ( {group.items.map((text, idx) => (
<motion.div key={idx} initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true, amount: 0.2 }} transition={{ delay: idx * 0.06, duration: 0.4 }} className="relative group"> <motion.div
key={idx}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.2 }}
transition={{ delay: idx * 0.06, duration: 0.4 }}
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"> <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">
<div className="relative flex-shrink-0"> <div className="relative flex-shrink-0">
<motion.div whileHover={{ rotate: 360, scale: 1.03 }} transition={{ duration: 0.6 }} className="w-10 h-10 sm:w-12 sm:h-12 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"> <motion.div
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M5 13l4 4L19 7"/></svg> whileHover={{ rotate: 360, scale: 1.03 }}
transition={{ duration: 0.6 }}
className="w-10 h-10 sm:w-12 sm:h-12 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"
>
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M5 13l4 4L19 7"
/>
</svg>
</motion.div> </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 className="absolute inset-0 bg-amber-500 rounded-xl blur-xl opacity-0 group-hover:opacity-30 transition-opacity duration-300" />
</div> </div>
<div className="flex-1 pt-1"> <div className="flex-1 pt-1">
<p className="text-xs sm:text-sm md:text-base text-gray-800 leading-relaxed font-medium">{text}</p> <p className="text-xs sm:text-sm md:text-base text-gray-800 leading-relaxed font-medium">
{text}
</p>
</div> </div>
<div className="flex-shrink-0 text-amber-500 opacity-0 group-hover:opacity-100 transition-all duration-300"> <div 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"> <svg
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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> </svg>
</div> </div>
</div> </div>
@ -557,11 +853,21 @@ export default function DepartmentDetail6() {
))} ))}
</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"> <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="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" /> <div className="w-2 h-2 bg-amber-500 rounded-full animate-pulse" />
<span className="text-xs sm:text-sm font-medium">{t("departmentDetail6.ui.servicesProfessional")}</span> <span className="text-xs sm:text-sm font-medium">
<div className="w-2 h-2 bg-orange-500 rounded-full animate-pulse" style={{ animationDelay: "0.5s" }} /> {t("departmentDetail6.ui.servicesProfessional")}
</span>
<div
className="w-2 h-2 bg-orange-500 rounded-full animate-pulse"
style={{ animationDelay: "0.5s" }}
/>
</div> </div>
</motion.div> </motion.div>
</motion.div> </motion.div>

View File

@ -320,9 +320,13 @@ export default function DepartmentDetail7() {
}; };
// جلب الأزرار/البيانات من الترجمة // جلب الأزرار/البيانات من الترجمة
const buttons = t("departmentDetail7.buttons", { returnObjects: true }); const buttons = [
{ id: 1, title: t("departmentDetail7.buttons.1"), key: "expertise" },
{ id: 2, title: t("departmentDetail7.buttons.2"), key: "works" },
];
const projectsTimeline = t("departmentDetail7.projectsTimeline.defaultProjects", { returnObjects: true }); const projectsTimeline = t("departmentDetail7.projectsTimeline.defaultProjects", { returnObjects: true });
const expertiseTexts = t("departmentDetail7.expertiseItems", { returnObjects: true }); const expertiseTextsRaw = t("departmentDetail7.expertiseItems", { returnObjects: true });
const expertiseTexts = Array.isArray(expertiseTextsRaw) ? expertiseTextsRaw : [];
const hero = t("departmentDetail7.hero", { returnObjects: true }); const hero = t("departmentDetail7.hero", { returnObjects: true });
const ui = t("departmentDetail7.ui", { returnObjects: true }); const ui = t("departmentDetail7.ui", { returnObjects: true });
const backToMenu = t("departmentDetail7.backToMenu"); const backToMenu = t("departmentDetail7.backToMenu");

View File

@ -15,7 +15,7 @@ function ProjectsTimeline({
dir = "rtl", dir = "rtl",
scrollLabel = "خط زمني قابل للتمرير", scrollLabel = "خط زمني قابل للتمرير",
prevLabel = "السابق", prevLabel = "السابق",
nextLabel = "التالي" nextLabel = "التالي",
}) { }) {
const wrapperRef = useRef(null); const wrapperRef = useRef(null);
const scrollRef = useRef(null); const scrollRef = useRef(null);
@ -25,7 +25,9 @@ function ProjectsTimeline({
useEffect(() => { useEffect(() => {
setItemsRefs((r) => { setItemsRefs((r) => {
const arr = Array(projects.length).fill().map((_, i) => r[i] || React.createRef()); const arr = Array(projects.length)
.fill()
.map((_, i) => r[i] || React.createRef());
return arr; return arr;
}); });
}, [projects.length]); }, [projects.length]);
@ -129,7 +131,11 @@ function ProjectsTimeline({
const scrollLeft = scrollContainer.scrollLeft; const scrollLeft = scrollContainer.scrollLeft;
const targetScroll = const targetScroll =
scrollLeft + itemRect.left - containerRect.left - containerRect.width / 2 + itemRect.width / 2; scrollLeft +
itemRect.left -
containerRect.left -
containerRect.width / 2 +
itemRect.width / 2;
scrollContainer.scrollTo({ left: targetScroll, behavior: "smooth" }); scrollContainer.scrollTo({ left: targetScroll, behavior: "smooth" });
setActiveItem(index); setActiveItem(index);
@ -186,7 +192,8 @@ function ProjectsTimeline({
return () => { return () => {
clearTimeout(t); clearTimeout(t);
if (scrollContainer) scrollContainer.removeEventListener("scroll", onScroll); if (scrollContainer)
scrollContainer.removeEventListener("scroll", onScroll);
window.removeEventListener("resize", onResize); window.removeEventListener("resize", onResize);
}; };
}, [itemsRefs, drawCurvedLines, setActiveItem]); }, [itemsRefs, drawCurvedLines, setActiveItem]);
@ -250,25 +257,65 @@ function ProjectsTimeline({
.projects-timeline-root.plain-bleed .project-card { max-width:420px; } .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%)" }; const mainStyle = plain
? { background: "#ffffff", paddingBottom: 0 }
: {
background:
"linear-gradient(135deg, var(--bg-start) 0%, var(--bg-mid) 30%, var(--bg-end) 60%)",
};
return ( return (
<div className={`projects-timeline-root w-full h-full ${plain ? "plain-bleed" : ""}`} dir={dir}> <div
className={`projects-timeline-root w-full h-full ${
plain ? "plain-bleed" : ""
}`}
dir={dir}
>
<style>{css}</style> <style>{css}</style>
<main className="w-full h-full overflow-hidden" style={mainStyle}> <main className="w-full h-full overflow-hidden" style={mainStyle}>
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
{!plain && ( {!plain && (
<header className="text-center py-8 px-4"> <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)" }}> <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} {mainTitle}
</h1> </h1>
<p id="subtitle" className={`${plain ? "text-base text-gray-700" : "text-xl text-white opacity-90"}`}>{subtitle}</p> <p
id="subtitle"
className={`${
plain
? "text-base text-gray-700"
: "text-xl text-white opacity-90"
}`}
>
{subtitle}
</p>
</header> </header>
)} )}
<div className="flex-1 relative"> <div className="flex-1 relative">
<div className="timeline-scroll h-full" id="timeline-scroll" ref={scrollRef} aria-label={scrollLabel}> <div
<div className="timeline-wrapper" id="timeline-wrapper" ref={wrapperRef}> className="timeline-scroll h-full"
id="timeline-scroll"
ref={scrollRef}
aria-label={scrollLabel}
>
<div
className="timeline-wrapper"
id="timeline-wrapper"
ref={wrapperRef}
>
<svg className="svg-container" id="timeline-svg" ref={svgRef} /> <svg className="svg-container" id="timeline-svg" ref={svgRef} />
{projects.map((project, idx) => ( {projects.map((project, idx) => (
<div <div
@ -297,8 +344,24 @@ function ProjectsTimeline({
</div> </div>
<div className="scroll-indicator"> <div className="scroll-indicator">
<button className="scroll-btn" aria-label={prevLabel} onClick={onPrev} disabled={currentIndex === 0} title={prevLabel}></button> <button
<button className="scroll-btn" aria-label={nextLabel} onClick={onNext} disabled={currentIndex === projects.length - 1} title={nextLabel}></button> className="scroll-btn"
aria-label={prevLabel}
onClick={onPrev}
disabled={currentIndex === 0}
title={prevLabel}
>
</button>
<button
className="scroll-btn"
aria-label={nextLabel}
onClick={onNext}
disabled={currentIndex === projects.length - 1}
title={nextLabel}
>
</button>
</div> </div>
</div> </div>
</div> </div>
@ -315,44 +378,110 @@ export default function DepartmentDetail8() {
const [active, setActive] = useState(null); const [active, setActive] = useState(null);
const hero = t("departmentDetail8.hero", { returnObjects: true }); const hero = t("departmentDetail8.hero", { returnObjects: true });
const buttons = t("departmentDetail8.buttons", { returnObjects: true });
const projectsTimeline = t("departmentDetail8.projectsTimeline.defaultProjects", { returnObjects: true }); const buttons = [
const expertiseTexts = t("departmentDetail8.expertiseItems", { returnObjects: true }); { id: 1, title: t("departmentDetail8.buttons.1"), key: "expertise" },
{ id: 2, title: t("departmentDetail8.buttons.2"), key: "works" },
];
const projectsTimeline = t(
"departmentDetail8.projectsTimeline.defaultProjects",
{ returnObjects: true }
);
const expertiseTextsRaw = t("departmentDetail8.expertiseItems", {
returnObjects: true,
});
const expertiseTexts = Array.isArray(expertiseTextsRaw)
? expertiseTextsRaw
: [];
const ui = t("departmentDetail8.ui", { returnObjects: true }); const ui = t("departmentDetail8.ui", { returnObjects: true });
const backToMenu = t("departmentDetail8.backToMenu"); const backToMenu = t("departmentDetail8.backToMenu");
const scrollLabels = t("departmentDetail8.scroll", { returnObjects: true }); const scrollLabels = t("departmentDetail8.scroll", { returnObjects: true });
const icons = [ const icons = [
( <svg
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24" key="i1"> className="w-7 h-7"
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.2" d="M3 7h13l3 3v7a1 1 0 01-1 1h-1a2 2 0 11-4 0H9a2 2 0 11-4 0H4a1 1 0 01-1-1V7zM16 7v4" /> fill="none"
</svg> stroke="currentColor"
), viewBox="0 0 24 24"
( key="i1"
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24" key="i2"> >
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.2" d="M4 7h4l4 5 4-5h4M5 19a2 2 0 104 0 2 2 0 00-4 0zm10 0a2 2 0 104 0 2 2 0 00-4 0z" /> <path
</svg> strokeLinecap="round"
), strokeLinejoin="round"
( strokeWidth="2.2"
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24" key="i3"> d="M3 7h13l3 3v7a1 1 0 01-1 1h-1a2 2 0 11-4 0H9a2 2 0 11-4 0H4a1 1 0 01-1-1V7zM16 7v4"
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.2" d="M3 7l9-4 9 4-9 4-9-4zM21 8v8a2 2 0 01-2 2H5a2 2 0 01-2-2V8" /> />
</svg> </svg>,
), <svg
( className="w-7 h-7"
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24" key="i4"> fill="none"
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.2" d="M3 12l4 4 8-8 4 4M14 7l3-3M7 17l-3 3" /> stroke="currentColor"
</svg> viewBox="0 0 24 24"
), key="i2"
( >
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24" key="i5"> <path
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.2" d="M3 9l9-5 9 5v8a2 2 0 01-2 2H5a2 2 0 01-2-2V9zM9 22V12" /> strokeLinecap="round"
</svg> strokeLinejoin="round"
), strokeWidth="2.2"
( d="M4 7h4l4 5 4-5h4M5 19a2 2 0 104 0 2 2 0 00-4 0zm10 0a2 2 0 104 0 2 2 0 00-4 0z"
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24" key="i6"> />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.2" d="M12 8v4l2 2M6.16 4.94l1.42 1.42M17.42 4.94l-1.42 1.42M4 13h2M18 13h2M6.16 19.06l1.42-1.42M17.42 19.06l-1.42-1.42" /> </svg>,
</svg> <svg
) className="w-7 h-7"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
key="i3"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.2"
d="M3 7l9-4 9 4-9 4-9-4zM21 8v8a2 2 0 01-2 2H5a2 2 0 01-2-2V8"
/>
</svg>,
<svg
className="w-7 h-7"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
key="i4"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.2"
d="M3 12l4 4 8-8 4 4M14 7l3-3M7 17l-3 3"
/>
</svg>,
<svg
className="w-7 h-7"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
key="i5"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.2"
d="M3 9l9-5 9 5v8a2 2 0 01-2 2H5a2 2 0 01-2-2V9zM9 22V12"
/>
</svg>,
<svg
className="w-7 h-7"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
key="i6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.2"
d="M12 8v4l2 2M6.16 4.94l1.42 1.42M17.42 4.94l-1.42 1.42M4 13h2M18 13h2M6.16 19.06l1.42-1.42M17.42 19.06l-1.42-1.42"
/>
</svg>,
]; ];
const expertiseItems = expertiseTexts.map((text, idx) => { const expertiseItems = expertiseTexts.map((text, idx) => {
@ -368,10 +497,14 @@ export default function DepartmentDetail8() {
setActive((prev) => (prev === key ? null : key)); setActive((prev) => (prev === key ? null : key));
}; };
const heroImage = active === "expertise" ? d34 : active === "works" ? d33 : d21; const heroImage =
active === "expertise" ? d34 : active === "works" ? d33 : d21;
return ( return (
<div dir={isRTL ? "rtl" : "ltr"} className="w-full min-h-screen bg-white pb-12"> <div
dir={isRTL ? "rtl" : "ltr"}
className="w-full min-h-screen bg-white pb-12"
>
<section className="relative"> <section className="relative">
<div className="w-full"> <div className="w-full">
<AnimatePresence mode="wait"> <AnimatePresence mode="wait">
@ -400,27 +533,71 @@ export default function DepartmentDetail8() {
<div className="max-w-7xl mx-auto px-4 sm:px-6 w-full"> <div className="max-w-7xl mx-auto px-4 sm:px-6 w-full">
<AnimatePresence mode="wait"> <AnimatePresence mode="wait">
{active === "expertise" ? ( {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 ${isRTL ? 'text-right' : 'text-left'}`}> <motion.div
<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">{hero.expertiseBadge}</div> key="expertise-title"
<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">{hero.expertiseTitle}</h2> initial={{ opacity: 0, x: -50 }}
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">{hero.expertiseSubtitle}</p> animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: 50 }}
transition={{ duration: 0.5 }}
className={`text-white max-w-4xl ${
isRTL ? "text-right" : "text-left"
}`}
>
<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">
{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">
{hero.expertiseTitle}
</h2>
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">
{hero.expertiseSubtitle}
</p>
</motion.div> </motion.div>
) : active === "works" ? ( ) : 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 ${isRTL ? 'text-right' : 'text-left'}`}> <motion.div
<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">{hero.worksBadge}</div> key="works-title"
<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">{hero.worksTitle}</h2> initial={{ opacity: 0, x: -50 }}
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">{hero.worksSubtitle}</p> animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: 50 }}
transition={{ duration: 0.5 }}
className={`text-white max-w-4xl ${
isRTL ? "text-right" : "text-left"
}`}
>
<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">
{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">
{hero.worksTitle}
</h2>
<p className="text-xs sm:text-sm md:text-xl text-gray-200 leading-relaxed font-semibold drop-shadow-lg">
{hero.worksSubtitle}
</p>
</motion.div> </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 ${isRTL ? 'text-right' : 'text-left'}`}> <motion.div
<h2 className="text-xl sm:text-2xl md:text-4xl lg:text-5xl font-extrabold drop-shadow-2xl leading-tight">{hero.defaultTitle}</h2> 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 ${
isRTL ? "text-right" : "text-left"
}`}
>
<h2 className="text-xl sm:text-2xl md:text-4xl lg:text-5xl font-extrabold drop-shadow-2xl leading-tight">
{hero.defaultTitle}
</h2>
</motion.div> </motion.div>
)} )}
</AnimatePresence> </AnimatePresence>
</div> </div>
</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 sm:block" style={{ zIndex: 99999 }}> <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 sm:block"
style={{ zIndex: 99999 }}
>
<AnimatePresence> <AnimatePresence>
{!active && ( {!active && (
<motion.div <motion.div
@ -438,10 +615,16 @@ export default function DepartmentDetail8() {
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.08, duration: 0.5 }} transition={{ delay: index * 0.08, duration: 0.5 }}
whileHover={{ scale: 1.03, y: -6, transition: { duration: 0.2 } }} whileHover={{
scale: 1.03,
y: -6,
transition: { duration: 0.2 },
}}
whileTap={{ scale: 0.97 }} whileTap={{ scale: 0.97 }}
onClick={() => handleButtonClick(b.key)} 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/85 backdrop-blur-sm`} 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/85 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-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="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" />
@ -450,12 +633,24 @@ export default function DepartmentDetail8() {
<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"> <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} {b.id}
</div> </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> <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> </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"> <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>{ui.clickToView}</span> <span>{ui.clickToView}</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"> <svg
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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> </svg>
</p> </p>
</div> </div>
@ -468,8 +663,16 @@ export default function DepartmentDetail8() {
</div> </div>
<div className="absolute bottom-0 left-0 right-0 z-10"> <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"> <svg
<path d="M0,0 C300,80 900,80 1200,0 L1200,120 L0,120 Z" fill="#ffffff" opacity="1"/> 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> </svg>
</div> </div>
</motion.div> </motion.div>
@ -496,17 +699,33 @@ export default function DepartmentDetail8() {
transition={{ delay: index * 0.05, duration: 0.35 }} transition={{ delay: index * 0.05, duration: 0.35 }}
whileHover={{ scale: 1.02 }} whileHover={{ scale: 1.02 }}
onClick={() => handleButtonClick(b.key)} 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`} 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"> <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} {b.id}
</div> </div>
<div className="flex-1"> <div className="flex-1">
<h3 className="text-sm font-bold text-gray-800">{b.title}</h3> <h3 className="text-sm font-bold text-gray-800">
<p className="text-xs text-gray-600 mt-1">{ui.clickToView}</p> {b.title}
</h3>
<p className="text-xs text-gray-600 mt-1">
{ui.clickToView}
</p>
</div> </div>
<svg className="w-5 h-5 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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> </svg>
</motion.button> </motion.button>
))} ))}
@ -519,21 +738,63 @@ export default function DepartmentDetail8() {
<section className="max-w-7xl mx-auto px-4 sm:px-6 md:px-6 -mt-6 md:-mt-8 relative z-20"> <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"> <AnimatePresence mode="wait">
{!active ? ( {!active ? (
<motion.div key="buttons-spacer" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.25 }} className="h-0" /> <motion.div
key="buttons-spacer"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.25 }}
className="h-0"
/>
) : active === "works" ? ( ) : 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.div
<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 ${isRTL ? 'mr-0 md:-mr-4' : 'ml-0 md:-ml-4'}`}> key="timeline-view"
<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"> initial={{ opacity: 0, y: 20 }}
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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 ${
isRTL ? "mr-0 md:-mr-4" : "ml-0 md:-ml-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> </svg>
<span>{backToMenu}</span> <span>{backToMenu}</span>
</motion.button> </motion.button>
<div style={{ position: 'relative', left: '50%', right: '50%', marginLeft: '-50vw', marginRight: '-50vw', width: '100vw' }}> <div
style={{
position: "relative",
left: "50%",
right: "50%",
marginLeft: "-50vw",
marginRight: "-50vw",
width: "100vw",
}}
>
<ProjectsTimeline <ProjectsTimeline
projects={projectsTimeline} projects={projectsTimeline}
plain={true} plain={true}
dir={isRTL ? 'rtl' : 'ltr'} dir={isRTL ? "rtl" : "ltr"}
mainTitle={hero.worksTitle} mainTitle={hero.worksTitle}
subtitle={hero.worksSubtitle} subtitle={hero.worksSubtitle}
scrollLabel={scrollLabels.ariaLabel} scrollLabel={scrollLabels.ariaLabel}
@ -543,10 +804,36 @@ export default function DepartmentDetail8() {
</div> </div>
</motion.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.div
<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 ${isRTL ? 'mr-0 md:-mr-4' : 'ml-0 md:-ml-4'}`}> key="details-view"
<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"> initial={{ opacity: 0, y: 20 }}
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M15 19l-7-7 7-7"/> 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 ${
isRTL ? "mr-0 md:-mr-4" : "ml-0 md:-ml-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> </svg>
<span>{backToMenu}</span> <span>{backToMenu}</span>
</motion.button> </motion.button>
@ -563,30 +850,60 @@ export default function DepartmentDetail8() {
> >
<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"> <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">
<div className="relative flex-shrink-0"> <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 shadow-lg group-hover:shadow-2xl transition-shadow duration-300 relative z-10"> <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 shadow-lg group-hover:shadow-2xl transition-shadow duration-300 relative z-10"
>
{item.icon} {item.icon}
</motion.div> </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 className="absolute inset-0 bg-amber-500 rounded-xl blur-xl opacity-0 group-hover:opacity-30 transition-opacity duration-300" />
</div> </div>
<div className="flex-1 pt-1"> <div className="flex-1 pt-1">
<p className="text-sm md:text-base text-gray-800 leading-relaxed font-medium group-hover:text-gray-900 transition-colors duration-300">{item.text}</p> <p className="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> </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"> <motion.div
<svg className="w-4 h-4 sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> initial={{ opacity: 0, x: -8 }}
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.2" d="M15 19l-7-7 7-7"/> 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.2"
d="M15 19l-7-7 7-7"
/>
</svg> </svg>
</motion.div> </motion.div>
</div> </div>
</motion.div> </motion.div>
))} ))}
<motion.div initial={{ opacity: 0, scale: 0.95 }} animate={{ opacity: 1, scale: 1 }} transition={{ delay: 0.6, duration: 0.45 }} className="mt-2 sm:mt-6 pt-4 border-t-2 border-gray-100 text-center col-span-full"> <motion.div
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ delay: 0.6, duration: 0.45 }}
className="mt-2 sm:mt-6 pt-4 border-t-2 border-gray-100 text-center col-span-full"
>
<div className="inline-flex items-center gap-2 sm:gap-3 text-gray-500"> <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" /> <div className="w-2 h-2 bg-amber-500 rounded-full animate-pulse" />
<span className="text-xs sm:text-sm font-medium">{ui.servicesProfessional}</span> <span className="text-xs sm:text-sm font-medium">
<div className="w-2 h-2 bg-orange-500 rounded-full animate-pulse" style={{ animationDelay: "0.5s" }} /> {ui.servicesProfessional}
</span>
<div
className="w-2 h-2 bg-orange-500 rounded-full animate-pulse"
style={{ animationDelay: "0.5s" }}
/>
</div> </div>
</motion.div> </motion.div>
</div> </div>

View File

@ -21,7 +21,11 @@ import d21 from "../../../../src/assets/Images/d21.jpeg";
import d22 from "../../../../src/assets/Images/d22.jpg"; import d22 from "../../../../src/assets/Images/d22.jpg";
const departments = [ const departments = [
{ id: 1, title: "قسم إنشاء وصيانة المنشآت الصناعية وخطوط الإنتاج", image: d1 }, {
id: 1,
title: "قسم إنشاء وصيانة المنشآت الصناعية وخطوط الإنتاج",
image: d1,
},
{ id: 2, title: "قسم تنفيذ المرافق السكنية والخدمية", image: d7 }, { id: 2, title: "قسم تنفيذ المرافق السكنية والخدمية", image: d7 },
{ id: 3, title: "قسم اعادة تأهيل وصيانة المباني", image: d14 }, { id: 3, title: "قسم اعادة تأهيل وصيانة المباني", image: d14 },
{ id: 4, title: "قسم محطات الوقود وصيانة المنشآت النفطية", image: d17 }, { id: 4, title: "قسم محطات الوقود وصيانة المنشآت النفطية", image: d17 },
@ -79,11 +83,14 @@ function DepartmentCard({ dept, offset, index }) {
const progressParallax = useTransform(scrollYProgress, [0, 1], [15, -15]); const progressParallax = useTransform(scrollYProgress, [0, 1], [15, -15]);
const y = useTransform([velocityParallax, progressParallax], ([v, p]) => v + p); const y = useTransform(
[velocityParallax, progressParallax],
([v, p]) => v + p
);
const handleClick = () => { const handleClick = () => {
if (dept.id === 1) { if (dept.id === 1) {
navigate("/departments/:id"); navigate("/departments/1");
} }
if (dept.id === 9) { if (dept.id === 9) {
navigate("/department-detail9"); navigate("/department-detail9");
@ -110,7 +117,9 @@ function DepartmentCard({ dept, offset, index }) {
} }
}; };
const translatedTitle = t(`departments.list.${dept.id - 1}`, { defaultValue: dept.title }); const translatedTitle = t(`departments.list.${dept.id - 1}`, {
defaultValue: dept.title,
});
return ( return (
<div <div
@ -140,7 +149,8 @@ function DepartmentCard({ dept, offset, index }) {
scale: s, scale: s,
y, y,
transformStyle: "preserve-3d", transformStyle: "preserve-3d",
boxShadow: "0 18px 50px rgba(2,6,23,0.12), 0 6px 18px rgba(2,6,23,0.06)", boxShadow:
"0 18px 50px rgba(2,6,23,0.12), 0 6px 18px rgba(2,6,23,0.06)",
}} }}
className="cursor-pointer w-full h-56 sm:h-72 md:h-96 lg:h-[28rem] object-cover rounded-2xl bg-white/20 backdrop-blur-md border border-white/10" className="cursor-pointer w-full h-56 sm:h-72 md:h-96 lg:h-[28rem] object-cover rounded-2xl bg-white/20 backdrop-blur-md border border-white/10"
/> />
@ -152,10 +162,14 @@ export default function Departments() {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<section id="departments" className="min-h-screen text-black bg-transparent" dir="rtl"> <section
id="departments"
className="min-h-screen text-black bg-transparent"
dir="rtl"
>
<header className="max-w-6xl mx-auto px-4 sm:px-6 md:px-8 pt-10 sm:pt-12 relative z-20"> <header className="max-w-6xl mx-auto px-4 sm:px-6 md:px-8 pt-10 sm:pt-12 relative z-20">
<h1 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-[#041c40] via-[#57acd9] to-[#041c40] drop-shadow-lg"> <h1 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-[#041c40] via-[#57acd9] to-[#041c40] drop-shadow-lg">
{t('departments.heading', { defaultValue: 'أقسامنا' })} {t("departments.heading", { defaultValue: "أقسامنا" })}
</h1> </h1>
</header> </header>

View File

@ -1,12 +1,16 @@
import React, { useEffect, useState, useRef } from "react"; import React, { useEffect, useState, useRef } from "react";
import styled from 'styled-components'; import styled from "styled-components";
import { useTranslation } from 'react-i18next'; import { useTranslation } from "react-i18next";
import REXNT from "../../../assets/Images/REXNT.png";
import TPSlogo from "../../../assets/Images/TPS-logo.png";
import NSC from "../../../assets/Images/NSC.png";
import LOGO from "../../../assets/Images/LOGO.png";
export default function EngineeringHeroFlowbite() { export default function EngineeringHeroFlowbite() {
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
const defaultConfig = { const defaultConfig = {
main_title: "عندما تطلب الرؤية مستشارًا, ويحتاج المخطط منفذًا استراتيجيًا…نكون القرار بالقيادة من الرؤية حتى التسليم", main_title:
"عندما تطلب الرؤية مستشارًا, ويحتاج المخطط منفذًا استراتيجيًا…نكون القرار بالقيادة من الرؤية حتى التسليم",
subtitle: subtitle:
"حلول متكاملة تشمل التصميم، التنفيذ، التشغيل، والصيانة\nللمشاريع الصناعية والمدنية، وفق أحدث المعايير والتقنيات", "حلول متكاملة تشمل التصميم، التنفيذ، التشغيل، والصيانة\nللمشاريع الصناعية والمدنية، وفق أحدث المعايير والتقنيات",
primary_color: "#e67e22", primary_color: "#e67e22",
@ -20,8 +24,8 @@ export default function EngineeringHeroFlowbite() {
const [config, setConfig] = useState({ const [config, setConfig] = useState({
...defaultConfig, ...defaultConfig,
main_title: t ? t('hero.main_title') : defaultConfig.main_title, main_title: t ? t("hero.main_title") : defaultConfig.main_title,
subtitle: t ? t('hero.subtitle') : defaultConfig.subtitle, subtitle: t ? t("hero.subtitle") : defaultConfig.subtitle,
}); });
const [isMounted, setIsMounted] = useState(false); const [isMounted, setIsMounted] = useState(false);
@ -34,7 +38,8 @@ export default function EngineeringHeroFlowbite() {
const link = document.createElement("link"); const link = document.createElement("link");
link.id = id; link.id = id;
link.rel = "stylesheet"; link.rel = "stylesheet";
link.href = "https://fonts.googleapis.com/css2?family=Cairo:wght@400;600;700;800&display=swap"; link.href =
"https://fonts.googleapis.com/css2?family=Cairo:wght@400;600;700;800&display=swap";
document.head.appendChild(link); document.head.appendChild(link);
} }
}, []); }, []);
@ -46,23 +51,23 @@ export default function EngineeringHeroFlowbite() {
useEffect(() => { useEffect(() => {
const updateFromI18n = () => { const updateFromI18n = () => {
const lang = i18n.language || 'en'; const lang = i18n.language || "en";
let main = t('hero.main_title'); let main = t("hero.main_title");
if (lang && lang.startsWith('en')) { if (lang && lang.startsWith("en")) {
main = main.replace(/[—–]/g, ' - '); main = main.replace(/[—–]/g, " - ");
} }
setConfig((c) => ({ setConfig((c) => ({
...c, ...c,
main_title: main, main_title: main,
subtitle: t('hero.subtitle'), subtitle: t("hero.subtitle"),
})); }));
document.documentElement.lang = lang; document.documentElement.lang = lang;
document.documentElement.dir = lang.startsWith('ar') ? 'rtl' : 'ltr'; document.documentElement.dir = lang.startsWith("ar") ? "rtl" : "ltr";
}; };
updateFromI18n(); updateFromI18n();
i18n.on && i18n.on('languageChanged', updateFromI18n); i18n.on && i18n.on("languageChanged", updateFromI18n);
return () => { return () => {
i18n.off && i18n.off('languageChanged', updateFromI18n); i18n.off && i18n.off("languageChanged", updateFromI18n);
}; };
}, [i18n, t]); }, [i18n, t]);
@ -70,23 +75,34 @@ export default function EngineeringHeroFlowbite() {
const main = mainTitleRef.current; const main = mainTitleRef.current;
const sub = subtitleRef.current; const sub = subtitleRef.current;
const baseFontStack = "Arial, sans-serif"; const baseFontStack = "Arial, sans-serif";
const font = (config.font_family || defaultConfig.font_family) + ", " + baseFontStack; const font =
(config.font_family || defaultConfig.font_family) + ", " + baseFontStack;
const baseSize = config.font_size || defaultConfig.font_size; const baseSize = config.font_size || defaultConfig.font_size;
const applyStyles = () => { const applyStyles = () => {
const lang = i18n.language || 'en'; const lang = i18n.language || "en";
const isArabic = lang.startsWith('ar'); const isArabic = lang.startsWith("ar");
const width = typeof window !== "undefined" ? window.innerWidth : 1024; const width = typeof window !== "undefined" ? window.innerWidth : 1024;
const responsiveBase = width <= 400 ? baseSize * 0.78 : width <= 640 ? baseSize * 0.88 : width <= 1024 ? baseSize * 0.96 : baseSize; const responsiveBase =
width <= 400
? baseSize * 0.78
: width <= 640
? baseSize * 0.88
: width <= 1024
? baseSize * 0.96
: baseSize;
const headingMultiplier = width <= 640 ? 2.6 : 3.2; const headingMultiplier = width <= 640 ? 2.6 : 3.2;
const subtitleMultiplier = width <= 640 ? 0.95 : 1.1; const subtitleMultiplier = width <= 640 ? 0.95 : 1.1;
const mainText = (config.main_title || defaultConfig.main_title).replace(/\s+/g, " ").trim(); const mainText = (config.main_title || defaultConfig.main_title)
.replace(/\s+/g, " ")
.trim();
const mainTextLength = mainText.length; const mainTextLength = mainText.length;
const lengthFactor = mainTextLength > 100 ? 0.78 : mainTextLength > 70 ? 0.86 : 1.0; const lengthFactor =
mainTextLength > 100 ? 0.78 : mainTextLength > 70 ? 0.86 : 1.0;
const maxFont = 68; const maxFont = 68;
const minFont = Math.max(Math.round(responsiveBase * 1.6), 14); const minFont = Math.max(Math.round(responsiveBase * 1.6), 14);
const root = document.documentElement; const root = document.documentElement;
root.style.setProperty('--base', `${responsiveBase}px`); root.style.setProperty("--base", `${responsiveBase}px`);
if (main) { if (main) {
const headingText = (config.main_title || defaultConfig.main_title) const headingText = (config.main_title || defaultConfig.main_title)
@ -96,12 +112,20 @@ export default function EngineeringHeroFlowbite() {
if (headingText.length === 1) { if (headingText.length === 1) {
main.textContent = headingText[0]; main.textContent = headingText[0];
} else { } else {
main.innerHTML = `<span style="display:block;line-height:1.02">${headingText[0]}</span><span style="display:block;font-weight:700;opacity:0.95;margin-top:6px">${headingText main.innerHTML = `<span style="display:block;line-height:1.02">${
headingText[0]
}</span><span style="display:block;font-weight:700;opacity:0.95;margin-top:6px">${headingText
.slice(1) .slice(1)
.join("<br/>")}</span>`; .join("<br/>")}</span>`;
} }
main.style.fontFamily = font; main.style.fontFamily = font;
const computedSize = Math.min(Math.max(Math.round(responsiveBase * headingMultiplier * lengthFactor), minFont), maxFont); const computedSize = Math.min(
Math.max(
Math.round(responsiveBase * headingMultiplier * lengthFactor),
minFont
),
maxFont
);
main.style.fontSize = `${computedSize}px`; main.style.fontSize = `${computedSize}px`;
main.style.color = config.text_color || defaultConfig.text_color; main.style.color = config.text_color || defaultConfig.text_color;
main.style.fontWeight = 800; main.style.fontWeight = 800;
@ -131,10 +155,22 @@ export default function EngineeringHeroFlowbite() {
sub.style.display = "block"; sub.style.display = "block";
} }
root.style.setProperty("--ehb-primary", config.primary_color || defaultConfig.primary_color); root.style.setProperty(
root.style.setProperty("--ehb-background", config.background_color || defaultConfig.background_color); "--ehb-primary",
root.style.setProperty("--ehb-surface", config.secondary_surface || defaultConfig.secondary_surface); config.primary_color || defaultConfig.primary_color
root.style.setProperty("--ehb-action", config.secondary_action || defaultConfig.secondary_action); );
root.style.setProperty(
"--ehb-background",
config.background_color || defaultConfig.background_color
);
root.style.setProperty(
"--ehb-surface",
config.secondary_surface || defaultConfig.secondary_surface
);
root.style.setProperty(
"--ehb-action",
config.secondary_action || defaultConfig.secondary_action
);
}; };
applyStyles(); applyStyles();
@ -155,20 +191,37 @@ export default function EngineeringHeroFlowbite() {
const OrangeActionButton = ({ onClick }) => { const OrangeActionButton = ({ onClick }) => {
return ( return (
<StyledWrapper> <StyledWrapper>
<button className="button" onClick={onClick} aria-label={t('hero.action')}> <button
{t('hero.action')} className="button"
<svg className="icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden> onClick={onClick}
<path fillRule="evenodd" d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zm4.28 10.28a.75.75 0 000-1.06l-3-3a.75.75 0 10-1.06 1.06l1.72 1.72H8.25a.75.75 0 000 1.5h5.69l-1.72 1.72a.75.75 0 101.06 1.06l3-3z" clipRule="evenodd" /> aria-label={t("hero.action")}
>
{t("hero.action")}
<svg
className="icon"
viewBox="0 0 24 24"
fill="currentColor"
aria-hidden
>
<path
fillRule="evenodd"
d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zm4.28 10.28a.75.75 0 000-1.06l-3-3a.75.75 0 10-1.06 1.06l1.72 1.72H8.25a.75.75 0 000 1.5h5.69l-1.72 1.72a.75.75 0 101.06 1.06l3-3z"
clipRule="evenodd"
/>
</svg> </svg>
</button> </button>
</StyledWrapper> </StyledWrapper>
); );
}; };
const isArabic = i18n.language && i18n.language.startsWith('ar'); const isArabic = i18n.language && i18n.language.startsWith("ar");
return ( return (
<div dir={isArabic ? "rtl" : "ltr"} className="h-screen w-full overflow-hidden content-container" style={{ background: "transparent" }}> <div
dir={isArabic ? "rtl" : "ltr"}
className="h-screen w-full overflow-hidden content-container"
style={{ background: "transparent" }}
>
<style>{` <style>{`
:root { --ehb-primary: #e67e22; --ehb-background: #000000; --ehb-surface: #95a5a6; --ehb-action: #34495e; --base: 16px } :root { --ehb-primary: #e67e22; --ehb-background: #000000; --ehb-surface: #95a5a6; --ehb-action: #34495e; --base: 16px }
@ -328,25 +381,57 @@ export default function EngineeringHeroFlowbite() {
<div className={`hero-section ${isMounted ? "is-mounted" : ""}`}> <div className={`hero-section ${isMounted ? "is-mounted" : ""}`}>
<div className="hero-overlay" /> <div className="hero-overlay" />
<div className={`hero-layout ${isArabic ? '' : 'layout-ltr'}`}> <div className={`hero-layout ${isArabic ? "" : "layout-ltr"}`}>
<div className="hero-left"> <div className="hero-left">
<img src="src/assets/Images/REXNT.png" alt="REXNT" /> <img src={REXNT} alt="REXNT" />
<div className="partner-logos" aria-hidden> <div className="partner-logos" aria-hidden>
<div className="partner-bubble" style={{ animationDelay: "0ms" }} aria-label="شريك TPS"> <div
<img src="src/assets/Images/TPS-logo.png" alt="TPS" /> className="partner-bubble"
style={{ animationDelay: "0ms" }}
aria-label="شريك TPS"
>
<img src={TPSlogo} alt="TPS" />
</div> </div>
<div className="partner-bubble" style={{ animationDelay: "180ms" }} aria-label="شريك NSC"> <div
<img src="src/assets/Images/NSC.png" alt="NSC" /> className="partner-bubble"
style={{ animationDelay: "180ms" }}
aria-label="شريك NSC"
>
<img src={NSC} alt="NSC" />
</div> </div>
<div className="partner-bubble" style={{ animationDelay: "360ms" }} aria-label="شريك LOGO"> <div
<img src="src/assets/Images/LOGO.png" alt="LOGO" /> className="partner-bubble"
style={{ animationDelay: "360ms" }}
aria-label="شريك LOGO"
>
<img src={LOGO} alt="LOGO" />
</div> </div>
</div> </div>
</div> </div>
<div className={`hero-content ${isArabic ? 'content-rtl' : 'content-ltr'}`}> <div
<h1 ref={mainTitleRef} className="hero-title text-white" style={{ fontWeight: 800, marginBottom: 16, textShadow: "2px 2px 10px rgba(0,0,0,0.6)" }} /> className={`hero-content ${
<p ref={subtitleRef} className="hero-subtitle text-white" style={{ maxWidth: 800, textShadow: "1px 1px 6px rgba(0,0,0,0.45)", lineHeight: 1.6 }} /> isArabic ? "content-rtl" : "content-ltr"
}`}
>
<h1
ref={mainTitleRef}
className="hero-title text-white"
style={{
fontWeight: 800,
marginBottom: 16,
textShadow: "2px 2px 10px rgba(0,0,0,0.6)",
}}
/>
<p
ref={subtitleRef}
className="hero-subtitle text-white"
style={{
maxWidth: 800,
textShadow: "1px 1px 6px rgba(0,0,0,0.45)",
lineHeight: 1.6,
}}
/>
<div className="action-wrapper" style={{ marginTop: 18 }}> <div className="action-wrapper" style={{ marginTop: 18 }}>
<OrangeActionButton onClick={goToDepartments} /> <OrangeActionButton onClick={goToDepartments} />
</div> </div>
@ -379,11 +464,22 @@ const StyledWrapper = styled.div`
cursor: pointer; cursor: pointer;
} }
.icon { width: 24px; height: 24px; transition: all 0.3s ease-in-out; } .icon {
width: 24px;
height: 24px;
transition: all 0.3s ease-in-out;
}
.button:hover { transform: scale(1.05); border-color: #fff9; } .button:hover {
.button:hover .icon { transform: translate(4px); } transform: scale(1.05);
.button:hover::before { animation: shine 1.5s ease-out infinite; } border-color: #fff9;
}
.button:hover .icon {
transform: translate(4px);
}
.button:hover::before {
animation: shine 1.5s ease-out infinite;
}
.button::before { .button::before {
content: ""; content: "";
@ -402,8 +498,14 @@ const StyledWrapper = styled.div`
} }
@keyframes shine { @keyframes shine {
0% { left: -100px; } 0% {
60% { left: 100%; } left: -100px;
to { left: 100%; } }
60% {
left: 100%;
}
to {
left: 100%;
}
} }
`; `;

File diff suppressed because it is too large Load Diff