Files
REXNT/src/Components/Sections/Home/Home.jsx
Rahaf 955a827d78
All checks were successful
Build frontend / build (push) Successful in 34s
Edit text
2026-01-14 13:26:50 +03:00

511 lines
20 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useState, useRef } from "react";
import styled from "styled-components";
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() {
const { t, i18n } = useTranslation();
const defaultConfig = {
main_title: "عندما تطلب الرؤية مستشارًا، ويحتاج المخطط منفذًا استراتيجيًا…\nنكون القرار بالقيادة من الرؤية حتى التسليم",
subtitle:
"حلول متكاملة تشمل التصميم، التنفيذ، التشغيل، والصيانة\nللمشاريع الصناعية والمدنية، وفق أحدث المعايير والتقنيات",
primary_color: "#e67e22",
background_color: "#000000",
text_color: "#ffffff",
secondary_surface: "#95a5a6",
secondary_action: "#34495e",
font_family: "Cairo",
font_size: 16,
};
const [config, setConfig] = useState({
...defaultConfig,
main_title: t ? t("hero.main_title") : defaultConfig.main_title,
subtitle: t ? t("hero.subtitle") : defaultConfig.subtitle,
});
const [isMounted, setIsMounted] = useState(false);
const mainTitleRef = useRef(null);
const subtitleRef = useRef(null);
useEffect(() => {
const id = "cairo-font-link";
if (!document.getElementById(id)) {
const link = document.createElement("link");
link.id = id;
link.rel = "stylesheet";
link.href =
"https://fonts.googleapis.com/css2?family=Cairo:wght@400;600;700;800&display=swap";
document.head.appendChild(link);
}
}, []);
useEffect(() => {
const tId = setTimeout(() => setIsMounted(true), 60);
return () => clearTimeout(tId);
}, []);
useEffect(() => {
const updateFromI18n = () => {
const lang = i18n.language || "en";
let main = t("hero.main_title");
if (lang && lang.startsWith("en")) {
main = main.replace(/[—–]/g, " - ");
}
setConfig((c) => ({
...c,
main_title: main,
subtitle: t("hero.subtitle"),
}));
document.documentElement.lang = lang;
document.documentElement.dir = lang.startsWith("ar") ? "rtl" : "ltr";
};
updateFromI18n();
i18n.on && i18n.on("languageChanged", updateFromI18n);
return () => {
i18n.off && i18n.off("languageChanged", updateFromI18n);
};
}, [i18n, t]);
useEffect(() => {
const main = mainTitleRef.current;
const sub = subtitleRef.current;
const baseFontStack = "Arial, sans-serif";
const font =
(config.font_family || defaultConfig.font_family) + ", " + baseFontStack;
const baseSize = config.font_size || defaultConfig.font_size;
const applyStyles = () => {
const lang = i18n.language || "en";
const isArabic = lang.startsWith("ar");
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 headingMultiplier = width <= 640 ? 2.6 : 3.2;
const subtitleMultiplier = width <= 640 ? 0.95 : 1.1;
const mainText = (config.main_title || defaultConfig.main_title)
.replace(/\s+/g, " ")
.trim();
const mainTextLength = mainText.length;
const lengthFactor =
mainTextLength > 100 ? 0.78 : mainTextLength > 70 ? 0.86 : 1.0;
const maxFont = 68;
const minFont = Math.max(Math.round(responsiveBase * 1.6), 14);
const root = document.documentElement;
root.style.setProperty("--base", `${responsiveBase}px`);
if (main) {
const headingText = (config.main_title || defaultConfig.main_title)
.split("\n")
.map((s) => s.trim())
.filter(Boolean);
if (headingText.length === 1) {
main.textContent = headingText[0];
} 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
.slice(1)
.join("<br/>")}</span>`;
}
main.style.fontFamily = font;
const computedSize = Math.min(
Math.max(
Math.round(responsiveBase * headingMultiplier * lengthFactor),
minFont
),
maxFont
);
main.style.fontSize = `${computedSize}px`;
main.style.color = config.text_color || defaultConfig.text_color;
main.style.fontWeight = 800;
main.style.textAlign = isArabic ? "right" : "left";
main.style.whiteSpace = "normal";
main.style.wordBreak = "break-word";
main.style.overflowWrap = "anywhere";
main.style.direction = isArabic ? "rtl" : "ltr";
main.style.display = "block";
}
if (sub) {
sub.innerHTML = (config.subtitle || defaultConfig.subtitle)
.split("\n")
.map((s) => `<div>${s.trim()}</div>`)
.join("");
sub.style.fontFamily = font;
const subSize = Math.round(responsiveBase * subtitleMultiplier);
sub.style.fontSize = `${subSize}px`;
sub.style.color = config.text_color || defaultConfig.text_color;
sub.style.textAlign = isArabic ? "right" : "left";
sub.style.maxWidth = "800px";
sub.style.whiteSpace = "normal";
sub.style.wordBreak = "break-word";
sub.style.overflowWrap = "anywhere";
sub.style.direction = isArabic ? "rtl" : "ltr";
sub.style.display = "block";
}
root.style.setProperty(
"--ehb-primary",
config.primary_color || defaultConfig.primary_color
);
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();
window.addEventListener("resize", applyStyles);
return () => window.removeEventListener("resize", applyStyles);
}, [config, i18n.language]);
const goToDepartments = (e) => {
e && e.preventDefault && e.preventDefault();
const el = document.getElementById("departments");
if (el) {
el.scrollIntoView({ behavior: "smooth", block: "start" });
} else {
window.scrollTo({ top: 0, behavior: "smooth" });
}
};
const OrangeActionButton = ({ onClick }) => {
return (
<StyledWrapper>
<button
className="button"
onClick={onClick}
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>
</button>
</StyledWrapper>
);
};
const isArabic = i18n.language && i18n.language.startsWith("ar");
return (
<div
dir={isArabic ? "rtl" : "ltr"}
className="h-screen w-full overflow-hidden content-container"
style={{ background: "transparent" }}
>
<style>{`
:root { --ehb-primary: #e67e22; --ehb-background: #000000; --ehb-surface: #95a5a6; --ehb-action: #34495e; --base: 16px }
.hero-section{position:relative;width:100%;height:100%;overflow:hidden}
.hero-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(to bottom, rgba(0,0,0,0.65), rgba(0,0,0,0.35));z-index:3}
.hero-layout{position:relative;z-index:10;height:100%;display:flex;align-items:center;justify-content:space-between;padding:clamp(12px,4vw,40px);gap:2rem;direction:ltr;flex-direction:row}
.hero-layout.layout-ltr{flex-direction:row-reverse}
.hero-left{flex:1;display:flex;align-items:center;justify-content:flex-start;padding:20px;position:relative;flex-direction:column}
.hero-left img{ max-width:100%; height:auto; display:block; transform: translateX(-20px) scale(0.995); opacity:1; will-change: transform, opacity; }
.hero-section.is-mounted .hero-left img{
transform: translateX(-120px) scale(0.96);
opacity: 0;
animation: slideInLeft 1200ms cubic-bezier(.2,.9,.2,1) 200ms both;
}
@keyframes slideInLeft {
0% { transform: translateX(-140px) scale(0.96); opacity: 0; filter: blur(2px); }
65% { transform: translateX(18px) scale(1.02); opacity: 1; filter: blur(0); }
100% { transform: translateX(0) scale(1); opacity: 1; }
}
.partner-logos{display:flex;gap:18px;margin-top:20px;align-items:flex-end;justify-content:flex-start}
.partner-bubble{
width:132px;height:132px;border-radius:9999px;background:linear-gradient(180deg, rgba(255,255,255,0.08), rgba(255,255,255,0.06));display:flex;align-items:center;justify-content:center;overflow:hidden;box-shadow:0 12px 36px rgba(0,0,0,0.45);backdrop-filter: blur(4px);transition:transform 420ms cubic-bezier(.2,.9,.2,1),box-shadow 420ms;
transform-origin:center;
transform: translateY(10px) scale(0.95);
opacity: 0;
will-change: transform, opacity;
}
.hero-section.is-mounted .partner-bubble{
animation:
popIn 900ms cubic-bezier(.2,.9,.2,1) both,
floatBubble 5s ease-in-out 1100ms infinite;
}
.partner-bubble img{max-width:78%;max-height:78%;object-fit:contain;filter:grayscale(0.06) saturate(0.95)}
.partner-bubble:hover{transform:translateY(-10px) scale(1.08);box-shadow:0 34px 72px rgba(0,0,0,0.55)}
@keyframes popIn {
0% { transform: translateY(30px) scale(0.6); opacity: 0; filter: blur(2px); }
65% { transform: translateY(-10px) scale(1.06); opacity: 1; filter: blur(0); }
100% { transform: translateY(0) scale(1); opacity: 1; }
}
@keyframes floatBubble{0%{transform:translateY(0) scale(1)}25%{transform:translateY(-10px) scale(1.03)}50%{transform:translateY(-24px) scale(1.07)}75%{transform:translateY(-10px) scale(1.03)}100%{transform:translateY(0) scale(1)}}
.partner-strip-wrap{position:fixed;left:0;bottom:14px;z-index:30;pointer-events:auto;width:100%;display:flex;justify-content:flex-start;padding-left:40px;padding-right:40px}
.partner-strip{backface-visibility:hidden;transform-style:preserve-3d;perspective:1000px;display:flex;align-items:center;gap:18px;padding:12px 20px;border-radius:14px;box-shadow:0 18px 40px rgba(0,0,0,0.55);
background:linear-gradient(90deg, rgba(6,23,58,0.98) 0%, rgba(30,50,90,0.9) 35%, rgba(230,126,34,0.98) 100%);
transform: translateX(-120%) translateZ(0) rotateX(6deg) skewY(-2deg);
animation: slideInStrip 1600ms cubic-bezier(.2,.9,.2,1) 600ms forwards;
will-change:transform,opacity;
}
@keyframes slideInStrip{
0%{opacity:0;transform:translateX(-120%) translateZ(0) rotateX(8deg) skewY(-4deg) scale(0.98)}
70%{transform:translateX(12px) translateZ(6px) rotateX(2deg) skewY(-1deg) scale(1.01);opacity:1}
100%{transform:translateX(0) translateZ(10px) rotateX(0deg) skewY(0deg) scale(1);opacity:1}
}
.partner-item{display:flex;align-items:center;justify-content:center;padding:6px;border-radius:10px;min-width:84px;min-height:48px;background:rgba(255,255,255,0.04);backdrop-filter:blur(4px);box-shadow:0 6px 18px rgba(0,0,0,0.45);transition:transform 400ms cubic-bezier(.2,.9,.2,1),box-shadow 400ms}
.partner-item img{max-height:36px;max-width:140px;object-fit:contain;display:block;filter:grayscale(0.06) saturate(0.95)}
.partner-item:hover{transform:translateY(-6px) translateZ(18px) rotateX(6deg);box-shadow:0 30px 50px rgba(0,0,0,0.55)}
@media (max-width: 1024px){
.partner-strip{padding:10px 14px;border-radius:12px}
.partner-item{min-width:72px;min-height:44px}
.partner-item img{max-height:30px}
.partner-strip-wrap{padding-left:20px;padding-right:20px;bottom:10px}
}
@media (max-width: 640px){
.partner-strip{gap:10px;padding:8px;border-radius:10px}
.partner-item img{max-height:24px}
.partner-logos{gap:12px}
.partner-bubble{width:100px;height:100px}
.partner-bubble img{max-width:64%;max-height:64%}
.hero-layout{gap:1rem}
}
.hero-content{flex:1;z-index:15;display:flex;flex-direction:column;justify-content:center;padding:clamp(12px,3.5vw,40px)}
.hero-content.content-rtl{align-items:flex-end}
.hero-content.content-ltr{align-items:flex-start}
.hero-title{ opacity:1; transform: translateX(0) translateY(0) scale(1); will-change: transform, opacity; }
.hero-subtitle{ opacity:1; transform: translateX(0) translateY(0) scale(1); will-change: transform, opacity; }
.hero-section.is-mounted .hero-title{
opacity:0;
transform: translateX(120px) translateY(10px) scale(0.995);
animation: slideFromRight 1000ms cubic-bezier(.2,.9,.2,1) 260ms both;
}
.hero-section.is-mounted .hero-subtitle{
opacity:0;
transform: translateX(96px) translateY(6px) scale(0.995);
animation: slideFromRight 1000ms cubic-bezier(.2,.9,.2,1) 520ms both;
}
@keyframes slideFromRight {
0% { opacity:0; transform: translateX(120px) translateY(18px) scale(0.98); filter: blur(2px); }
65% { transform: translateX(-8px) translateY(-8px) scale(1.02); opacity:1; filter: blur(0); }
100% { opacity:1; transform: translateX(0) translateY(0) scale(1); }
}
@media (max-width: 768px){
.hero-layout{flex-direction:column;align-items:center;text-align:center}
.hero-layout.layout-ltr{flex-direction:column;align-items:center;text-align:center}
.hero-content{align-items:center;padding-inline:16px}
.hero-content.content-rtl, .hero-content.content-ltr { align-items: center !important }
.hero-title{font-size:calc(var(--base,16px) * 2.0) !important; text-align:center !important}
.hero-subtitle{font-size:calc(var(--base,16px) * 1.0) !important; text-align:center !important}
.action-wrapper{align-self:center !important}
}
.button {
position: relative;
transition: all 0.3s ease-in-out;
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.2);
padding-block: 0.5rem;
padding-inline: 1.25rem;
background-color: var(--ehb-primary, #e67e22);
border-radius: 9999px;
display: flex;
align-items: center;
justify-content: center;
color: #ffff;
gap: 10px;
font-weight: bold;
border: 3px solid #ffffff4d;
outline: none;
overflow: hidden;
font-size: 15px;
cursor: pointer;
transform: translateY(0) scale(1);
opacity: 1;
}
.hero-section.is-mounted .button{
transform: scale(0.6);
opacity: 0;
animation: popIn 900ms cubic-bezier(.2,.9,.2,1) 760ms both;
will-change: transform, opacity;
}
.icon { width: 24px; height: 24px; transition: all 0.3s ease-in-out; }
.button:hover { transform: scale(1.05); border-color: #fff9; }
.button:hover .icon { transform: translate(4px); }
.button:hover::before { animation: shine 1.5s ease-out infinite; }
.button::before {
content: "";
position: absolute;
width: 100px;
height: 100%;
background-image: linear-gradient(
120deg,
rgba(255, 255, 255, 0) 30%,
rgba(255, 255, 255, 0.8),
rgba(255, 255, 255, 0) 70%
);
top: 0;
left: -100px;
opacity: 0.6;
}
@keyframes popIn {
0% { transform: translateY(30px) scale(0.6); opacity: 0; filter: blur(2px); }
65% { transform: translateY(-10px) scale(1.06); opacity: 1; filter: blur(0); }
100% { transform: translateY(0) scale(1); opacity: 1; }
}
@keyframes shine {
0% { left: -100px; }
60% { left: 100%; }
to { left: 100%; }
}
`}</style>
<div className={`hero-section ${isMounted ? "is-mounted" : ""}`}>
<div className="hero-overlay" />
<div className={`hero-layout ${isArabic ? "" : "layout-ltr"}`}>
<div className="hero-left">
<img src={REXNT} alt="REXNT" />
<div className="partner-logos" aria-hidden>
<div
className="partner-bubble"
style={{ animationDelay: "0ms" }}
aria-label="شريك TPS"
>
<img src={TPSlogo} alt="TPS" />
</div>
<div
className="partner-bubble"
style={{ animationDelay: "180ms" }}
aria-label="شريك NSC"
>
<img src={NSC} alt="NSC" />
</div>
<div
className="partner-bubble"
style={{ animationDelay: "360ms" }}
aria-label="شريك LOGO"
>
<img src={LOGO} alt="LOGO" />
</div>
</div>
</div>
<div
className={`hero-content ${
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 }}>
<OrangeActionButton onClick={goToDepartments} />
</div>
</div>
</div>
</div>
</div>
);
}
const StyledWrapper = styled.div`
.button {
position: relative;
transition: all 0.3s ease-in-out;
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.2);
padding-block: 0.5rem;
padding-inline: 1.25rem;
background-color: var(--ehb-primary, #e67e22);
border-radius: 9999px;
display: flex;
align-items: center;
justify-content: center;
color: #ffff;
gap: 10px;
font-weight: bold;
border: 3px solid #ffffff4d;
outline: none;
overflow: hidden;
font-size: 15px;
cursor: pointer;
}
.icon {
width: 24px;
height: 24px;
transition: all 0.3s ease-in-out;
}
.button:hover {
transform: scale(1.05);
border-color: #fff9;
}
.button:hover .icon {
transform: translate(4px);
}
.button:hover::before {
animation: shine 1.5s ease-out infinite;
}
.button::before {
content: "";
position: absolute;
width: 100px;
height: 100%;
background-image: linear-gradient(
120deg,
rgba(255, 255, 255, 0) 30%,
rgba(255, 255, 255, 0.8),
rgba(255, 255, 255, 0) 70%
);
top: 0;
left: -100px;
opacity: 0.6;
}
@keyframes shine {
0% {
left: -100px;
}
60% {
left: 100%;
}
to {
left: 100%;
}
}
`;