Initial commit REXNT project

This commit is contained in:
Rahaf
2025-12-23 17:09:40 +03:00
commit 914078190f
45 changed files with 7797 additions and 0 deletions

View File

@ -0,0 +1,336 @@
import { useState, useEffect } from "react";
// Import all images statically
// import home1 from "../assets/home1.jpg";
// import home1Mobile from "../assets/home1-2.jpg";
// import home2 from "../assets/home2.jpg";
// import home2Mobile from "../assets/home2-2.jpg";
// import home3 from "../assets/home3.png";
// import home4 from "../assets/home4.png";
// // import home4Mobile from "../assets/home4-2.jpg";
// import home5 from "../assets/home5.png";
// import home6 from "../assets/home6.jpg";
// import home6Mobile from "../assets/home6-2.jpg";
// import home7 from "../assets/home7.jpg";
// import home7Mobile from "../assets/home7-2.jpg";
// import home8 from "../assets/home8.jpg";
// import home8Mobile from "../assets/home8-2.jpg";
// import home9 from "../assets/home9.jpg";
// import home10 from "../assets/home10.jpg";
// Services images
import gasStation from "../assets/Images/gasstation.jpg";
// List all critical images that need to be preloaded
const imagesToPreload = [
// Home images
// home1,
// home1Mobile,
// home2,
// home2Mobile,
// home3,
// home4,
// home4Mobile,
// home5,
// home6,
// home6Mobile,
// home7,
// home7Mobile,
// home8,
// home8Mobile,
// home9,
// home10,
// Services images
gasStation,
];
const ImagePreloader = ({ children }) => {
const [imagesLoaded, setImagesLoaded] = useState(false);
const [progress, setProgress] = useState(0);
useEffect(() => {
let loadedCount = 0;
const totalImages = imagesToPreload.length;
const preloadImages = async () => {
try {
const loadImage = (src) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.src = src;
img.onload = () => {
loadedCount++;
setProgress(Math.floor((loadedCount / totalImages) * 100));
resolve();
};
img.onerror = reject;
});
};
await Promise.all(imagesToPreload.map(loadImage));
setImagesLoaded(true);
} catch (error) {
console.error("Failed to preload images:", error);
// Continue anyway after a timeout
setTimeout(() => setImagesLoaded(true), 3000);
}
};
preloadImages();
}, []);
if (!imagesLoaded) {
return (
<div className="fixed inset-0 bg-gradient-to-b from-[#0A2540] to-[#10375C] flex flex-col items-center justify-center z-50">
{/* Animated background effect */}
<div className="absolute inset-0 overflow-hidden opacity-10">
<div className="absolute top-0 left-0 w-full h-full">
{[...Array(20)].map((_, i) => (
<div
key={i}
className="absolute rounded-full bg-white/30"
style={{
width: `${Math.random() * 10 + 5}px`,
height: `${Math.random() * 10 + 5}px`,
top: `${Math.random() * 100}%`,
left: `${Math.random() * 100}%`,
animationDuration: `${Math.random() * 10 + 10}s`,
animationDelay: `${Math.random() * 5}s`,
}}
/>
))}
</div>
</div>
{/* Company logo or branding could go here */}
<div className="mb-12 text-[#F3C623] text-3xl font-bold tracking-wider">
TPS
</div>
{/* 3D-style Fuel Tank */}
<div className="relative w-72 h-56 mb-8 perspective-800">
{/* Tank body with 3D effect */}
<div
className="absolute bottom-0 left-1/2 transform -translate-x-1/2 w-56 h-40 rounded-lg overflow-hidden shadow-2xl"
style={{
background: "linear-gradient(145deg, #0A2540 0%, #102A45 100%)",
boxShadow:
"inset 0 0 15px rgba(0,0,0,0.5), 0 10px 20px rgba(0,0,0,0.3)",
border: "1px solid rgba(255,255,255,0.1)",
}}
>
{/* Glass effect overlay */}
<div className="absolute inset-0 bg-gradient-to-br from-white/5 to-transparent pointer-events-none"></div>
{/* Tank Cap with metallic effect */}
<div
className="absolute -top-3 left-1/2 transform -translate-x-1/2 w-10 h-6 rounded-t-md"
style={{
background:
"linear-gradient(to bottom, #F3C623 0%, #EB8317 100%)",
boxShadow: "0 -2px 5px rgba(0,0,0,0.2)",
}}
>
<div className="absolute top-1 left-1/2 transform -translate-x-1/2 w-6 h-1 bg-[#0A2540]/30 rounded-full"></div>
</div>
{/* Fuel Level with dynamic wave effect */}
<div
className="absolute bottom-0 left-0 right-0 transition-all duration-500 ease-out"
style={{
height: `${progress}%`,
background: "linear-gradient(to top, #EB8317 0%, #F3C623 100%)",
boxShadow: "0 -5px 15px rgba(235,131,23,0.3)",
}}
>
{/* Animated wave effect at the top of fuel */}
<div className="absolute -top-2 left-0 w-full h-4 animate-wave">
<div
className="relative w-[200%] h-full"
style={{
backgroundImage:
"linear-gradient(to right, transparent 0%, rgba(255,255,255,0.3) 50%, transparent 100%)",
backgroundSize: "50% 100%",
animation: "moveWave 3s linear infinite",
}}
></div>
</div>
{/* Bubbles with varied animations */}
{[...Array(8)].map((_, i) => (
<div
key={i}
className="absolute rounded-full bg-white/20"
style={{
width: `${Math.random() * 6 + 2}px`,
height: `${Math.random() * 6 + 2}px`,
bottom: `${Math.random() * 80}%`,
left: `${Math.random() * 90 + 5}%`,
animation: `bubble ${
Math.random() * 3 + 2
}s ease-in infinite ${Math.random() * 2}s`,
}}
/>
))}
</div>
{/* Tank level markings with glow effect */}
<div className="absolute top-0 left-0 h-full w-full flex flex-col justify-between pointer-events-none">
{[...Array(4)].map((_, i) => (
<div
key={i}
className="w-full border-b border-[#F3C623]/20 h-1/4"
style={{
boxShadow:
progress > 75 - i * 25
? "0 1px 3px rgba(243,198,35,0.3)"
: "none",
}}
>
<div className="absolute right-0 w-2 h-0.5 bg-[#F3C623]/40"></div>
</div>
))}
</div>
</div>
{/* Fuel Gauge with realistic dial */}
<div
className="absolute top-0 right-0 w-20 h-20 rounded-full flex items-center justify-center"
style={{
background:
"radial-gradient(circle at center, #102A45 0%, #0A2540 70%)",
boxShadow:
"inset 0 0 10px rgba(0,0,0,0.5), 0 5px 15px rgba(0,0,0,0.2)",
border: "2px solid rgba(235,131,23,0.7)",
}}
>
{/* Gauge markings */}
{[...Array(9)].map((_, i) => {
const rotation = -135 + i * 30;
const isLarge = i % 2 === 0;
return (
<div
key={i}
className={`absolute w-${isLarge ? "1.5" : "1"} h-${
isLarge ? "3" : "2"
} bg-[#F3C623]/${isLarge ? "70" : "40"}`}
style={{
transform: `rotate(${rotation}deg) translateY(-7px)`,
transformOrigin: "bottom center",
}}
/>
);
})}
{/* Gauge needle with smooth animation */}
<div
className="absolute w-1 h-9 bg-gradient-to-t from-[#EB8317] to-[#F3C623] rounded-t-full origin-bottom"
style={{
transform: `rotate(${-135 + progress * 2.7}deg)`,
transition: "transform 1s cubic-bezier(0.34, 1.56, 0.64, 1)",
boxShadow: "0 0 5px rgba(243,198,35,0.5)",
}}
>
<div className="absolute -top-1 left-1/2 transform -translate-x-1/2 w-2 h-2 rounded-full bg-[#F3C623] shadow-lg"></div>
</div>
{/* Center pin */}
<div className="absolute w-4 h-4 bg-[#0A2540] rounded-full border-2 border-[#EB8317] shadow-inner"></div>
{/* E and F indicators */}
<div className="absolute bottom-4 left-4 text-[#F3C623]/70 text-xs font-bold">
E
</div>
<div className="absolute bottom-4 right-4 text-[#F3C623]/70 text-xs font-bold">
F
</div>
</div>
</div>
{/* Progress indicator with animated glow */}
<div className="relative">
<p
className="text-white text-2xl font-bold"
style={{
textShadow: "0 0 10px rgba(255,255,255,0.3)",
}}
>
{progress}%
</p>
<div
className="absolute -inset-4 rounded-full opacity-0"
style={{
background:
"radial-gradient(circle, rgba(243,198,35,0.3) 0%, transparent 70%)",
animation: "pulse 2s ease-in-out infinite",
}}
></div>
</div>
<p className="mt-2 text-gray-300 font-medium tracking-wide">
Filling your tank...
</p>
{/* Advanced animations */}
{/* <style jsx>{`
@keyframes bubble {
0% {
transform: translateY(0) scale(0.8);
opacity: 0;
}
20% {
opacity: 0.8;
transform: translateY(-10px) scale(1);
}
80% {
opacity: 0.8;
transform: translateY(-30px) scale(0.9);
}
100% {
transform: translateY(-40px) scale(0.3);
opacity: 0;
}
}
@keyframes pulse {
0% {
opacity: 0;
transform: scale(0.8);
}
50% {
opacity: 0.5;
transform: scale(1.1);
}
100% {
opacity: 0;
transform: scale(0.8);
}
}
@keyframes moveWave {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
.perspective-800 {
perspective: 800px;
}
.animate-wave {
overflow: hidden;
}
`}</style> */}
</div>
);
}
return <>{children}</>;
};
export default ImagePreloader;

View File

@ -0,0 +1,87 @@
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import ukFlag from "../../assets/uk-flag.svg";
import deFlag from "../../assets/de-flag.svg";
import arFlag from "../../assets/syriaflag.svg";
import frFlag from "../../assets/france-flag-icon.svg";
import itFlag from "../../assets/italy-flag-icon.svg";
import cnFlag from "../../assets/china-flag-icon.svg";
const LanguageSwitcher = () => {
const { i18n } = useTranslation();
const [isOpen, setIsOpen] = useState(false);
const languages = [
{ code: "en", name: "English", flag: ukFlag },
{ code: "ar", name: "العربية", flag: arFlag },
{ code: "de", name: "Deutsch", flag: deFlag },
{ code: "zh", name: "中文", flag: cnFlag },
{ code: "fr", name: "Français", flag: frFlag },
{ code: "it", name: "Italiano", flag: itFlag },
];
const currentLanguage =
languages.find((lang) => lang.code === i18n.language) || languages[0];
const changeLanguage = (langCode) => {
i18n.changeLanguage(langCode);
setIsOpen(false);
if (langCode === "ar") {
document.documentElement.dir = "rtl";
document.documentElement.lang = "ar";
} else {
document.documentElement.dir = "ltr";
document.documentElement.lang = langCode;
}
};
const menuPosition =
document.documentElement.dir === "rtl" ? "left-0" : "right-0"; // toggle position based on dir
return (
<div className="relative inline-block text-left">
<button
onClick={() => setIsOpen(!isOpen)}
className="inline-flex items-center font-bold text-lg px-3 py-2 text-white rounded-lg cursor-pointer hover:bg-gray-100/10 dark:hover:bg-gray-700 transition"
>
<img
src={currentLanguage.flag}
alt={currentLanguage.name}
className="w-10 h-6"
/>
<span className="hidden sm:inline ms-2">{currentLanguage.name}</span>
</button>
{isOpen && (
<div
className={`absolute top-12 ${menuPosition} z-50 w-44 bg-white dark:bg-gray-700 divide-y divide-gray-100 dark:divide-gray-600 rounded-lg shadow`}
>
<ul className="py-2">
{languages.map((language) => (
<li key={language.code}>
<button
onClick={() => changeLanguage(language.code)}
className={`w-full text-left block px-4 py-2 text-sm hover:bg-gray-100 dark:hover:bg-gray-600 flex items-center gap-3 ${
currentLanguage.code === language.code
? "bg-gray-50 text-blue-600 dark:bg-gray-600"
: "text-gray-800 dark:text-white"
}`}
>
<img
src={language.flag}
alt={language.name}
className="w-10 h-6"
/>
<span>{language.name}</span>
</button>
</li>
))}
</ul>
</div>
)}
</div>
);
};
export default LanguageSwitcher;

View File

@ -0,0 +1,133 @@
import React, { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-scroll";
import LanguageSwitcher from "../LanguageSwitcher/LanguageSwitcher";
import "../../index.css";
const Navbar = () => {
const { t, i18n } = useTranslation();
const [menuOpen, setMenuOpen] = useState(false);
const [activeSection, setActiveSection] = useState("home");
const toggleMenu = () => {
setMenuOpen(!menuOpen);
};
// Handle scroll to update active section
useEffect(() => {
const handleScroll = () => {
const sections = ["home", "services", "about", "contact"];
const scrollPosition = window.scrollY + 100;
for (const section of sections) {
const element =
document.getElementById(section) ||
document.querySelector(`[name="${section}"]`);
if (element) {
const offsetTop = element.offsetTop;
const offsetHeight = element.offsetHeight;
if (
scrollPosition >= offsetTop &&
scrollPosition < offsetTop + offsetHeight
) {
setActiveSection(section);
break;
}
}
}
};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
// Update document direction when language changes
useEffect(() => {
if (i18n.language === "ar") {
document.documentElement.dir = "rtl";
document.documentElement.lang = "ar";
} else {
document.documentElement.dir = "ltr";
document.documentElement.lang = i18n.language;
}
}, [i18n.language]);
const navItems = [
{ key: "home", label: t("nav.home") },
{ key: "services", label: t("nav.services") },
{ key: "about", label: t("nav.about") },
{ key: "contact", label: t("nav.contact") },
];
return (
<nav className="bg-white/10 backdrop-blur-lg fixed top-0 w-full z-50 shadow h-14">
<div className="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto py-2 px-4">
{/* الشعار */}
<img
src="src/assets/TPS-logo.png"
className="h-8 sm:h-10 md:h-12 transition-all duration-300"
alt="TPS Logo"
/>
{/* الجانب الأيمن */}
<div className="flex items-center md:order-2 space-x-1 md:space-x-0 rtl:space-x-reverse relative">
{/* Language Switcher */}
<LanguageSwitcher />
{/* زر القائمة للجوال */}
<button
onClick={toggleMenu}
type="button"
className="inline-flex items-center right--30 p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700 ml-2"
aria-controls="navbar-menu"
aria-expanded={menuOpen}
>
<span className="sr-only">Open main menu</span>
<svg className="w-5 h-5" viewBox="0 0 17 14" fill="none">
<path
d="M1 1h15M1 7h15M1 13h15"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</button>
</div>
{/* روابط الأقسام */}
<div
className={`w-full md:flex md:w-auto md:order-1 transition-all duration-300 ease-in-out ${
menuOpen ? "block" : "hidden"
}`}
id="navbar-menu"
>
<ul className="flex flex-col md:flex-row bg-white dark:bg-gray-900 md:bg-transparent md:dark:bg-transparent p-4 md:p-0 rounded-lg shadow-md md:shadow-none space-y-2 md:space-y-0 md:space-x-6 mt-4 md:mt-0 divide-y divide-gray-200 md:divide-y-0">
{navItems.map((item) => (
<li key={item.key} className="pt-2 md:pt-0">
<Link
to={item.key}
smooth
duration={500}
spy={true}
offset={0}
onSetActive={() => setActiveSection(item.key)}
className={`block text-center md:inline cursor-pointer text-lg font-semibold transition duration-200 ${
activeSection === item.key
? "text-yellow-500"
: "text-gray-800 dark:text-white hover:text-yellow-500"
}`}
>
{item.label}
</Link>
</li>
))}
</ul>
</div>
</div>
</nav>
);
};
export default Navbar;

View File

@ -0,0 +1,30 @@
.grow-img {
animation: growIn 1s ease-out forwards;
}
@keyframes growIn {
0% {
transform: scale(0.8);
opacity: 0.8;
}
100% {
transform: scale(1);
opacity: 1;
}
}
@keyframes soft-blink {
0%,
100% {
opacity: 0.5;
transform: translateX(0);
}
50% {
opacity: 1;
transform: translateX(4px);
}
}
.animate-soft-blink {
animation: soft-blink 3s infinite ease-in-out;
}

View File

@ -0,0 +1,72 @@
import React, { useEffect } from "react";
import { Element } from "react-scroll";
import { useTranslation } from "react-i18next";
import AOS from "aos";
import "aos/dist/aos.css";
const About = () => {
const { t } = useTranslation();
const home10 = "https://i.imgur.com/MW2Sk0y.jpg";
useEffect(() => {
AOS.init({ duration: 1000, once: false });
const handleScroll = () => {
AOS.refresh();
};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
return (
<Element name="about">
<section
className="w-full h-screen px-4 sm:px-6 lg:px-16 py-12 sm:py-16 text-black font-sans relative overflow-hidden"
style={{ direction: "rtl", backgroundColor: "#111827" }}
>
{/* صورة الخلفية */}
<div
className="relative w-full sm:w-3/4 mx-auto z-0"
data-aos="fade-right"
style={{
borderRadius: "12px",
border: "1px solid #EB8323",
boxShadow:
"0 0 15px 5px rgba(235, 131, 35, 0.4), 0 0 8px 2px rgba(235, 131, 35, 0.3)",
}}
>
<img
src={home10}
alt="شخص"
className="w-full h-[450px] sm:h-[500px] md:h-[600px] object-cover rounded-lg transition-all duration-300"
loading="eager"
fetchPriority="high"
/>
</div>
{/* مربع النص المتراكب */}
<div
className="z-10 max-w-full px-4 sm:px-0 -mt-20 sm:mt-0 sm:absolute sm:bottom-10 sm:right-10
bg-white/20 backdrop-blur-md text-black p-6 sm:p-12 rounded-xl shadow-2xl
flex flex-col sm:max-w-md"
data-aos="fade-left"
>
<h1 className="mb-4 sm:mb-6 text-3xl sm:text-5xl font-extrabold md:text-6xl lg:text-7xl text-center self-center mt-0">
<span className="text-transparent bg-clip-text bg-gradient-to-r from-[#10375C] to-[#F3C623]">
{t('about.title')}
</span>
</h1>
<p className="text-lg sm:text-2xl leading-relaxed flex-grow text-center">
{t('about.description')}
</p>
</div>
</section>
</Element>
);
};
export default About;

View File

@ -0,0 +1,448 @@
import { useTranslation } from "react-i18next";
import {
FaMapMarkerAlt,
FaPhoneAlt,
FaEnvelope,
FaWhatsapp,
FaPaperPlane,
} from "react-icons/fa";
import emailjs from "@emailjs/browser";
import { useRef, useState } from "react";
import { motion } from "framer-motion";
const Contact = () => {
const { t } = useTranslation();
const form = useRef();
const [message, setMessage] = useState({ text: "", type: "" });
const [isLoading, setIsLoading] = useState(false);
const sendEmail = (e) => {
e.preventDefault();
setIsLoading(true);
setMessage({ text: "", type: "" });
emailjs
.sendForm(
"service_dynf5hg",
"template_l4ik4he",
form.current,
"rRjr_WNgPp7_rGno1"
)
.then(
(result) => {
console.log("Message sent:", result.text);
setMessage({
text: t("contact.successMessage") || "Message sent successfully!",
type: "success",
});
form.current.reset();
setIsLoading(false);
setTimeout(() => setMessage({ text: "", type: "" }), 5000);
},
(error) => {
console.error("Failed to send message:", error.text);
setMessage({
text:
t("contact.errorMessage") ||
"Failed to send message. Please try again.",
type: "error",
});
setIsLoading(false);
setTimeout(() => setMessage({ text: "", type: "" }), 5000);
}
);
};
return (
<section
id="contact"
className="relative min-h-screen py-16 px-4 sm:px-6 font-sans"
style={{
direction: "rtl",
background: "linear-gradient(135deg, #dceafe 0%, #e8f4ff 25%, #c6e2ff 50%, #a3d0ff 75%, #23558f 100%)"
}}
>
<div className="absolute inset-0 overflow-hidden">
<div className="absolute -top-10 -right-40 w-80 h-80 bg-[#3c5ee3] rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-pulse"></div>
<div className="absolute -bottom-10 -left-40 w-80 h-80 bg-[#2ecc71] rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-pulse delay-1000"></div>
<div className="absolute top-1/2 left-1/3 w-60 h-60 bg-[#9b59b6] rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-pulse delay-500"></div>
<div className="absolute bottom-0 left-0 w-full h-32 bg-gradient-to-t from-[#3c5ee3]/30 to-transparent"></div>
</div>
<div className="relative z-10 w-full max-w-6xl mx-auto">
<motion.div
initial={{ y: -50, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.8 }}
className="text-center mb-12"
>
<h1 className="pt-0 mb-0 text-2xl font-extrabold md:text-5xl lg:text-6xl">
<motion.span
className="bg-clip-text text-transparent bg-gradient-to-r from-[#2d59b3] via-blue-200 to-[#32a896]"
animate={{
backgroundPosition: ["0% 50%", "100% 50%", "0% 50%"]
}}
transition={{
duration: 5,
repeat: Infinity,
ease: "linear"
}}
style={{
backgroundSize: "200% 100%"
}}
>
{t("contact.title")}
</motion.span>
</h1>
</motion.div>
<div className="flex flex-col lg:flex-row-reverse gap-8 items-start">
<motion.div
initial={{ x: 50, opacity: 0 }}
animate={{ x: 0, opacity: 1 }}
transition={{ duration: 0.8, delay: 0.2 }}
className="space-y-4 lg:w-1/2"
>
<motion.div
whileHover={{ y: -5, scale: 1.02 }}
transition={{ duration: 0.3 }}
className="group relative bg-white/95 backdrop-blur-sm p-6 rounded-2xl shadow-lg border border-gray-100 hover:border-[#3c5ee3]/50 hover:shadow-2xl transition-all duration-300"
>
<div className="flex items-start gap-4">
<motion.div
whileHover={{ rotate: [0, -10, 10, 0] }}
transition={{ duration: 0.5 }}
className="p-3 rounded-xl bg-gradient-to-br from-[#23558f] to-[#3360b2] text-white shadow-lg"
>
<FaMapMarkerAlt className="text-2xl" />
</motion.div>
<div className="flex-1">
<h3 className="text-lg font-bold text-gray-800 mb-2">
{t("contact.address")}
</h3>
<p className="text-gray-600 text-sm leading-relaxed whitespace-pre-line">
{t("contact.addressText")}
</p>
</div>
</div>
<motion.div
className="absolute inset-0 rounded-2xl bg-gradient-to-br from-[#3c5ee3]/0 via-[#3c5ee3]/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500"
initial={false}
/>
<motion.div
className="absolute bottom-0 left-1/2 h-1 w-0 group-hover:w-3/4 bg-gradient-to-r from-transparent via-[#3c5ee3] to-transparent rounded-full"
initial={{ x: "-50%", width: "0%" }}
whileHover={{ width: "75%" }}
transition={{ duration: 0.3 }}
/>
</motion.div>
<motion.div
whileHover={{ y: -5, scale: 1.02 }}
transition={{ duration: 0.3 }}
className="group relative bg-white/95 backdrop-blur-sm p-6 rounded-2xl shadow-lg border border-gray-100 hover:border-[#3c5ee3]/50 hover:shadow-2xl transition-all duration-300"
>
<div className="flex items-start gap-4">
<motion.div
whileHover={{ rotate: [0, -10, 10, 0] }}
transition={{ duration: 0.5 }}
className="p-3 rounded-xl bg-gradient-to-br from-[#3c5ee3] to-[#5c7ce3] text-white shadow-lg"
>
<FaPhoneAlt className="text-2xl" />
</motion.div>
<div className="flex-1">
<h3 className="text-lg font-bold text-gray-800 mb-3">
{t("contact.phone")}
</h3>
<div className="space-y-3">
<div className="flex items-center justify-between bg-gradient-to-r from-[#e8f4ff] to-[#dceafe] rounded-xl p-3 hover:from-[#dceafe] hover:to-[#c6e2ff] transition-all duration-300">
<span className="text-[#23558f] font-medium">0965656631</span>
<div className="flex items-center gap-2">
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
className="p-2 rounded-full bg-gradient-to-r from-[#2ecc71] to-[#1abc9c] text-white hover:shadow-lg transition-all duration-300"
>
<FaPhoneAlt className="text-sm" />
</motion.button>
</div>
</div>
<div className="flex items-center justify-between bg-gradient-to-r from-[#e8f4ff] to-[#dceafe] rounded-xl p-3 hover:from-[#dceafe] hover:to-[#c6e2ff] transition-all duration-300">
<a
href="https://wa.me/963965656631"
target="_blank"
rel="noopener noreferrer"
className="text-[#23558f] font-medium hover:text-[#3c5ee3] transition-colors"
>
963965656631
</a>
<div className="flex items-center gap-2">
<motion.a
href="https://wa.me/963965656631"
target="_blank"
rel="noopener noreferrer"
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
className="p-2 rounded-full bg-gradient-to-r from-[#25D366] to-[#128C7E] text-white hover:shadow-lg transition-all duration-300"
>
<FaWhatsapp className="text-sm" />
</motion.a>
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
className="p-2 rounded-full bg-gradient-to-r from-[#23558f] to-[#3360b2] text-white hover:shadow-lg transition-all duration-300"
>
<FaPhoneAlt className="text-sm" />
</motion.button>
</div>
</div>
</div>
</div>
</div>
<motion.div
className="absolute inset-0 rounded-2xl bg-gradient-to-br from-[#3c5ee3]/0 via-[#3c5ee3]/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500"
initial={false}
/>
</motion.div>
<motion.div
whileHover={{ y: -5, scale: 1.02 }}
transition={{ duration: 0.3 }}
className="group relative bg-white/95 backdrop-blur-sm p-6 rounded-2xl shadow-lg border border-gray-100 hover:border-[#3c5ee3]/50 hover:shadow-2xl transition-all duration-300"
>
<div className="flex items-start gap-4">
<motion.div
whileHover={{ rotate: [0, -10, 10, 0] }}
transition={{ duration: 0.5 }}
className="p-3 rounded-xl bg-gradient-to-br from-[#2ecc71] to-[#1abc9c] text-white shadow-lg"
>
<FaEnvelope className="text-2xl" />
</motion.div>
<div className="flex-1">
<h3 className="text-lg font-bold text-gray-800 mb-2">
{t("contact.email")}
</h3>
<a
href="mailto:info@TPS-STATIONS.COM"
className="inline-block bg-gradient-to-r from-[#e8f4ff] to-[#dceafe] text-[#23558f] font-medium rounded-xl px-4 py-3 hover:from-[#dceafe] hover:to-[#c6e2ff] hover:text-[#3c5ee3] hover:shadow-lg transition-all duration-300"
>
Info@TPS-STATIONS.COM
</a>
</div>
</div>
<motion.div
className="absolute inset-0 rounded-2xl bg-gradient-to-br from-[#3c5ee3]/0 via-[#3c5ee3]/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500"
initial={false}
/>
<motion.div
className="absolute bottom-0 left-1/2 h-1 w-0 group-hover:w-3/4 bg-gradient-to-r from-transparent via-[#2ecc71] to-transparent rounded-full"
initial={{ x: "-50%", width: "0%" }}
whileHover={{ width: "75%" }}
transition={{ duration: 0.3 }}
/>
</motion.div>
</motion.div>
<motion.div
initial={{ x: -50, opacity: 0 }}
animate={{ x: 0, opacity: 1 }}
transition={{ duration: 0.8, delay: 0.4 }}
className="group relative bg-white/95 backdrop-blur-sm p-8 rounded-2xl shadow-2xl border border-gray-100 hover:border-[#3c5ee3]/50 hover:shadow-3xl transition-all duration-500 lg:w-1/2"
>
<div className="relative mb-3 pt-3">
<h2 className="text-2xl md:text-3xl font-bold text-center">
<span className="bg-clip-text text-transparent bg-gradient-to-r from-[#23558f] via-[#3c5ee3] to-[#2ecc71]">
{t("contact.formTitle")}
</span>
</h2>
<div className="absolute -bottom-2 left-1/2 transform -translate-x-1/2 w-24 h-1 bg-gradient-to-r from-[#23558f] via-[#3c5ee3] to-[#2ecc71] rounded-full"></div>
</div>
<form
ref={form}
onSubmit={sendEmail}
className="space-y-2"
>
<div className="group/field">
<label className="block mb-1 font-semibold text-gray-700 text-base transition-colors duration-300 group-hover/field:text-[#23558f]">
{t("contact.name")}
</label>
<div className="relative">
<input
type="text"
name="user_name"
required
className="w-full border-2 border-gray-200 p-4 rounded-xl bg-white text-gray-800 text-base placeholder-gray-400 focus:outline-none focus:ring-4 focus:ring-[#3c5ee3]/30 focus:border-[#3c5ee3] transition-all duration-300 hover:border-[#3c5ee3]/50 hover:shadow-lg hover:shadow-[#3c5ee3]/10"
placeholder={t("contact.namePlaceholder")}
/>
<div className="absolute inset-0 rounded-xl bg-gradient-to-r from-[#3c5ee3]/5 to-[#2ecc71]/5 opacity-0 hover:opacity-100 transition-opacity duration-300 pointer-events-none"></div>
</div>
</div>
<div className="group/field">
<label className="block mb-1 font-semibold text-gray-700 text-base transition-colors duration-300 group-hover/field:text-[#23558f]">
{t("contact.email")}
</label>
<div className="relative">
<input
type="email"
name="user_email"
required
className="w-full border-2 border-gray-200 p-4 rounded-xl bg-white text-gray-800 text-base placeholder-gray-400 focus:outline-none focus:ring-4 focus:ring-[#3c5ee3]/30 focus:border-[#3c5ee3] transition-all duration-300 hover:border-[#3c5ee3]/50 hover:shadow-lg hover:shadow-[#3c5ee3]/10"
placeholder={t("contact.emailPlaceholder")}
/>
<div className="absolute inset-0 rounded-xl bg-gradient-to-r from-[#3c5ee3]/5 to-[#2ecc71]/5 opacity-0 hover:opacity-100 transition-opacity duration-300 pointer-events-none"></div>
</div>
</div>
<div className="group/field">
<label className="block mb-2 font-semibold text-gray-700 text-base transition-colors duration-300 group-hover/field:text-[#23558f]">
{t("contact.message")}
</label>
<div className="relative">
<textarea
name="user_message"
required
className="w-full border-2 border-gray-200 p-4 rounded-xl resize-none bg-white text-gray-800 text-base placeholder-gray-400 focus:outline-none focus:ring-4 focus:ring-[#3c5ee3]/30 focus:border-[#3c5ee3] transition-all duration-300 hover:border-[#3c5ee3]/50 hover:shadow-lg hover:shadow-[#3c5ee3]/10 min-h-[120px]"
placeholder={t("contact.messagePlaceholder")}
></textarea>
<div className="absolute inset-0 rounded-xl bg-gradient-to-r from-[#3c5ee3]/5 to-[#2ecc71]/5 opacity-0 hover:opacity-100 transition-opacity duration-300 pointer-events-none"></div>
</div>
</div>
{message.text && (
<motion.div
initial={{ scale: 0.9, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
className={`p-4 rounded-xl text-center font-medium transition-all duration-500 ${
message.type === "success"
? "bg-gradient-to-r from-[#2ecc71]/20 to-[#1abc9c]/20 border border-[#2ecc71]/50 text-[#2ecc71] shadow-lg shadow-[#2ecc71]/20"
: "bg-gradient-to-r from-[#e74c3c]/20 to-[#c0392b]/20 border border-[#e74c3c]/50 text-[#e74c3c] shadow-lg shadow-[#e74c3c]/20"
}`}
>
<div className="flex items-center justify-center gap-2">
{message.type === "success" ? (
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M5 13l4 4L19 7"
/>
</svg>
) : (
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
</svg>
)}
{message.text}
</div>
</motion.div>
)}
<div className="pt-2">
<motion.button
type="submit"
disabled={isLoading}
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
className={`group/btn relative w-full bg-gradient-to-r from-[#23558f] via-[#3c5ee3] to-[#2ecc71] text-white px-6 py-4 text-lg font-semibold rounded-xl hover:shadow-2xl hover:shadow-[#3c5ee3]/30 transition-all duration-500 overflow-hidden ${
isLoading ? "opacity-70 cursor-not-allowed" : ""
}`}
>
<span className="relative z-10 flex items-center justify-center gap-2">
{isLoading ? (
<>
<svg
className="animate-spin w-5 h-5"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
{t("contact.send")}...
</>
) : (
<>
{t("contact.send")}
<FaPaperPlane className="w-5 h-5 transform group-hover/btn:translate-x-1 transition-transform duration-300" />
</>
)}
</span>
{!isLoading && (
<div className="absolute inset-0 bg-gradient-to-r from-white/0 via-white/20 to-white/0 transform -skew-x-12 -translate-x-full group-hover/btn:translate-x-full transition-transform duration-1000"></div>
)}
</motion.button>
</div>
</form>
<div className="absolute top-0 right-0 w-20 h-20 bg-gradient-to-br from-[#23558f]/10 to-[#3360b2]/10 rounded-full -translate-y-1/2 translate-x-1/2"></div>
<div className="absolute bottom-0 left-0 w-16 h-16 bg-gradient-to-br from-[#2ecc71]/10 to-[#1abc9c]/10 rounded-full translate-y-1/2 -translate-x-1/2"></div>
</motion.div>
</div>
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.6 }}
className="mt-16 p-8 rounded-2xl shadow-2xl text-center relative overflow-hidden"
style={{
background: "linear-gradient(135deg, #23558f 0%, #3360b2 33%, #3c5ee3 66%, #2ecc71 100%)"
}}
>
<div className="absolute inset-0">
<div className="absolute top-0 right-0 w-32 h-32 bg-white/10 rounded-full blur-2xl"></div>
<div className="absolute bottom-0 left-0 w-32 h-32 bg-white/10 rounded-full blur-2xl"></div>
</div>
<div className="relative z-10">
<h3 className="text-xl md:text-2xl font-bold text-white mb-4">
{t('contact.contactSection.title')}
</h3>
<p className="text-white/90 text-lg mb-6 max-w-2xl mx-auto">
{t('contact.contactSection.description')}
</p>
<div className="flex flex-wrap justify-center gap-4">
{t('contact.contactSection.badges', { returnObjects: true }).map((badge, index) => (
<motion.div
key={index}
whileHover={{ scale: 1.05, y: -2 }}
whileTap={{ scale: 0.95 }}
className="px-4 py-2 bg-white/20 rounded-full text-white text-sm font-medium backdrop-blur-sm hover:bg-white/30 transition-all duration-300 cursor-pointer"
>
{badge}
</motion.div>
))}
</div>
</div>
</motion.div>
</div>
</section>
);
};
export default Contact;

View File

@ -0,0 +1,279 @@
import React, { useState, useEffect } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Element } from "react-scroll";
import { FaWhatsapp, FaPhone, FaEnvelope } from "react-icons/fa";
import { useTranslation } from "react-i18next";
import "../../../index.css";
const home1 = "https://i.imgur.com/g4fVyLj.jpg";
const home1Mobile = "https://i.imgur.com/NNeCIAj.jpg";
const home2 = "https://i.imgur.com/d9enpvc.jpg";
const home2Mobile = "https://i.imgur.com/a85P9Q8.jpg";
const home3 = "https://i.imgur.com/nWTJcjz.jpg";
const home4 = "https://i.imgur.com/btajXYO.jpg";
const home4Mobile = "https://i.imgur.com/BZnHa4v.jpg";
const home6 = "https://i.imgur.com/gtwlzDA.jpg";
const home6Mobile = "https://i.imgur.com/xs8OB15.jpg";
const home7 = "https://i.imgur.com/kSErZeJ.jpg";
const home7Mobile = "https://i.imgur.com/02ftPiK.jpg";
const home8 = "https://i.imgur.com/0gsQF8L.jpg";
const home8Mobile = "https://i.imgur.com/vey37dG.jpg";
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: { staggerChildren: 0.3, when: "beforeChildren" },
},
};
const itemVariants = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0, transition: { duration: 0.8 } },
};
const Home = () => {
const { t } = useTranslation();
const [currentIndex, setCurrentIndex] = useState(0);
const [menuOpen, setMenuOpen] = useState(false);
const [isMobile, setIsMobile] = useState(false);
const phrases = t("home.phrases", { returnObjects: true });
useEffect(() => {
const updateSize = () => setIsMobile(window.innerWidth < 640);
updateSize();
window.addEventListener("resize", updateSize);
return () => window.removeEventListener("resize", updateSize);
}, []);
useEffect(() => {
const interval = setInterval(() => {
setCurrentIndex((prev) => (prev + 1) % phrases.length);
}, 4000);
return () => clearInterval(interval);
}, [phrases.length]);
const nextPhrase = () => {
setCurrentIndex((prev) => (prev + 1) % phrases.length);
};
const prevPhrase = () => {
setCurrentIndex((prev) => (prev - 1 + phrases.length) % phrases.length);
};
const getBackgroundImage = () => {
switch (currentIndex) {
case 0:
return isMobile ? home2Mobile : home2;
case 1:
return home3;
case 2:
return isMobile ? home4Mobile : home4;
case 3:
return isMobile ? home6Mobile : home6;
case 4:
return isMobile ? home8Mobile : home8;
case 5:
return isMobile ? home7Mobile : home7;
case 6:
return isMobile ? home1Mobile : home1;
default:
return "";
}
};
return (
<Element name="home">
<div className="relative h-screen w-full" dir="rtl">
{/* الخلفية */}
<div
className="absolute inset-0 bg-cover bg-center z-0 transition-all duration-1000"
style={{ backgroundImage: `url('${getBackgroundImage()}')` }}
loading="eager"
fetchPriority="high"
/>
<div className="absolute inset-0 bg-black/50 z-10" />
{/* المحتوى */}
<div className="relative z-20 flex flex-col items-center justify-center h-full w-full px-4 text-white text-center">
<motion.div
className="flex flex-col items-center justify-center gap-y-6 w-full max-w-screen-sm sm:max-w-2xl md:max-w-4xl"
variants={containerVariants}
initial="hidden"
animate="visible"
>
{/* العنوان المتغير */}
<motion.div
className="relative flex items-center justify-between w-full px-2 sm:px-4"
variants={itemVariants}
>
<motion.button
onClick={prevPhrase}
className="text-2xl sm:text-4xl p-1 sm:p-2 rounded bg-transparent text-[var(--primary-color)] hover:scale-110 transition-transform z-10"
aria-label="السابق"
>
<svg
viewBox="0 0 32 32"
strokeWidth={2}
stroke="currentColor"
className="w-8 h-8 sm:w-10 sm:h-10"
fill="none"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M11 6l10 10-10 10"
/>
</svg>
</motion.button>
<div className="relative h-[120px] sm:h-[150px] w-full flex justify-center items-center px-2">
<AnimatePresence mode="wait">
<motion.span
key={currentIndex}
className="absolute text-xl sm:text-3xl md:text-5xl font-bold text-[var(--primary-color)] text-center px-2 max-w-full break-words"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.5 }}
>
{phrases[currentIndex]}
</motion.span>
</AnimatePresence>
</div>
<motion.button
onClick={nextPhrase}
className="text-2xl sm:text-4xl p-1 sm:p-2 rounded bg-transparent text-[var(--primary-color)] hover:scale-110 transition-transform z-10"
aria-label="التالي"
>
<svg
viewBox="0 0 32 32"
strokeWidth={2}
stroke="currentColor"
className="w-8 h-8 sm:w-10 sm:h-10"
fill="none"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M21 6L11 16l10 10"
/>
</svg>
</motion.button>
</motion.div>
{/* وصف إضافي */}
<motion.div className="w-full px-2 sm:px-4" variants={itemVariants}>
<div className="text-sm sm:text-lg md:text-2xl text-white space-y-1">
<p>{t("home.subtitle1")}</p>
<p>{t("home.subtitle2")}</p>
</div>
</motion.div>
{/* زر تواصل معنا */}
<motion.div
className="w-full flex justify-center"
variants={itemVariants}
>
<div className="relative">
<motion.button
onClick={() => setMenuOpen((prev) => !prev)}
whileHover={{ scale: 1.05 }}
className="relative inline-flex items-center justify-center px-8 py-2.5 overflow-hidden tracking-tighter text-white bg-[#EB8317] rounded-md group"
style={{ zIndex: 30 }}
>
<span className="absolute w-0 h-0 transition-all duration-500 ease-out bg-[rgba(10,25,70,0.9)] rounded-full group-hover:w-56 group-hover:h-56"></span>
<span className="absolute bottom-0 left-0 h-full -ml-2">
<svg
xmlns="http://www.w3.org/2000/svg"
className="w-auto h-full opacity-100 object-stretch"
viewBox="0 0 487 487"
>
<path
fillOpacity=".1"
fillRule="nonzero"
fill="#FFF"
d="M0 .3c67 2.1 134.1 4.3 186.3 37 52.2 32.7 89.6 95.8 112.8 150.6 23.2 54.8 32.3 101.4 61.2 149.9 28.9 48.4 77.7 98.8 126.4 149.2H0V.3z"
/>
</svg>
</span>
<span className="absolute top-0 right-0 w-12 h-full -mr-3">
<svg
xmlns="http://www.w3.org/2000/svg"
className="object-cover w-full h-full"
viewBox="0 0 487 487"
>
<path
fillOpacity=".1"
fillRule="nonzero"
fill="#FFF"
d="M487 486.7c-66.1-3.6-132.3-7.3-186.3-37s-95.9-85.3-126.2-137.2c-30.4-51.8-49.3-99.9-76.5-151.4C70.9 109.6 35.6 54.8.3 0H487v486.7z"
/>
</svg>
</span>
<span className="absolute inset-0 w-full h-full -mt-1 rounded-lg opacity-30 bg-gradient-to-b from-transparent via-transparent to-gray-200"></span>
<span className="relative text-base font-semibold">
{t("home.contactUs")}
</span>
</motion.button>
<AnimatePresence>
{menuOpen && (
<motion.div
initial={{ opacity: 0, x: 20, y: -10 }}
animate={{ opacity: 1, x: 0, y: 10 }}
exit={{ opacity: 0, x: 20, y: -10 }}
transition={{ duration: 0.3 }}
className={`absolute top-16 ${
isMobile ? "right-0" : "sm:right-32"
} bg-[rgba(10,25,70,0.9)] text-white rounded-lg shadow-lg py-5 px-5 z-40`}
>
<a
href="https://wa.me/963965656631"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-3 text-sm py-2 px-3 rounded hover:bg-[rgba(235,131,23,0.3)] transition-colors"
>
<FaWhatsapp className="text-xl" />
<span>963965656631</span>
</a>
<a
href="https://wa.me/963965656635"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-3 text-sm py-2 px-3 rounded hover:bg-[rgba(235,131,23,0.3)] transition-colors"
>
<FaWhatsapp className="text-xl" />
<FaPhone className="text-xl" />
<span>963965656635</span>
</a>
<a
href="mailto:info@TPS-STATIONS.COM"
className="flex items-center gap-3 text-sm py-2 px-3 rounded hover:bg-[rgba(235,131,23,0.3)] transition-colors"
>
<FaEnvelope className="text-xl" />
<span>info@TPS-STATIONS.COM</span>
</a>
</motion.div>
)}
</AnimatePresence>
</div>
</motion.div>
</motion.div>
</div>
</div>
</Element>
);
};
export default Home;

View File

@ -0,0 +1,656 @@
import React, { useState, useEffect } from "react";
import { Element } from "react-scroll";
import { useTranslation } from "react-i18next";
import { motion, AnimatePresence } from "framer-motion";
import {
Globe,
MessageSquare,
Bell,
Package,
BarChart3,
Zap,
Shield,
Users,
Clock,
CheckCircle
} from "lucide-react";
const CARDS_PER_PAGE = 4;
const Services = () => {
const { t, ready } = useTranslation();
const servicesData = [
{
id: "service-1",
title: t('tradesafe.services.platform.title'),
description: t('tradesafe.services.platform.description'),
details: t('tradesafe.services.platform.details'),
icon: <Globe className="w-10 h-10" />,
color: "from-[#23558f] to-[#3360b2]",
bgColor: "bg-gradient-to-br from-[#23558f]/20 to-[#3360b2]/20",
features: t('tradesafe.services.platform.features', { returnObjects: true })
},
{
id: "service-2",
title: t('tradesafe.services.orders.title'),
description: t('tradesafe.services.orders.description'),
details: t('tradesafe.services.orders.details'),
icon: <Package className="w-10 h-10" />,
color: "from-[#3360b2] to-[#3c5ee3]",
bgColor: "bg-gradient-to-br from-[#3360b2]/20 to-[#3c5ee3]/20",
features: t('tradesafe.services.orders.features', { returnObjects: true })
},
{
id: "service-3",
title: t('tradesafe.services.communication.title'),
description: t('tradesafe.services.communication.description'),
details: t('tradesafe.services.communication.details'),
icon: <MessageSquare className="w-10 h-10" />,
color: "from-[#3c5ee3] to-[#5c7ce3]",
bgColor: "bg-gradient-to-br from-[#3c5ee3]/20 to-[#5c7ce3]/20",
features: t('tradesafe.services.communication.features', { returnObjects: true })
},
{
id: "service-4",
title: t('tradesafe.services.notifications.title'),
description: t('tradesafe.services.notifications.description'),
details: t('tradesafe.services.notifications.details'),
icon: <Bell className="w-10 h-10" />,
color: "from-[#4a90e2] to-[#6aa8f2]",
bgColor: "bg-gradient-to-br from-[#4a90e2]/20 to-[#6aa8f2]/20",
features: t('tradesafe.services.notifications.features', { returnObjects: true })
},
{
id: "service-5",
title: t('tradesafe.services.dashboard.title'),
description: t('tradesafe.services.dashboard.description'),
details: t('tradesafe.services.dashboard.details'),
icon: <BarChart3 className="w-10 h-10" />,
color: "from-[#2ecc71] to-[#1abc9c]",
bgColor: "bg-gradient-to-br from-[#2ecc71]/20 to-[#1abc9c]/20",
features: t('tradesafe.services.dashboard.features', { returnObjects: true })
},
{
id: "service-6",
title: t('tradesafe.services.solutions.title'),
description: t('tradesafe.services.solutions.description'),
details: t('tradesafe.services.solutions.details'),
icon: <Shield className="w-10 h-10" />,
color: "from-[#9b59b6] to-[#8e44ad]",
bgColor: "bg-gradient-to-br from-[#9b59b6]/20 to-[#8e44ad]/20",
features: t('tradesafe.services.solutions.features', { returnObjects: true })
},
{
id: "service-7",
title: t('tradesafe.services.speed.title'),
description: t('tradesafe.services.speed.description'),
details: t('tradesafe.services.speed.details'),
icon: <Zap className="w-10 h-10" />,
color: "from-[#f39c12] to-[#e67e22]",
bgColor: "bg-gradient-to-br from-[#f39c12]/20 to-[#e67e22]/20",
features: t('tradesafe.services.speed.features', { returnObjects: true })
},
{
id: "service-8",
title: t('tradesafe.services.network.title'),
description: t('tradesafe.services.network.description'),
details: t('tradesafe.services.network.details'),
icon: <Users className="w-10 h-10" />,
color: "from-[#3498db] to-[#2980b9]",
bgColor: "bg-gradient-to-br from-[#3498db]/20 to-[#2980b9]/20",
features: t('tradesafe.services.network.features', { returnObjects: true })
}
];
const reasonsToChooseUs = [
{
icon: <Zap className="w-8 h-8" />,
text: t('tradesafe.reasons.speed.text'),
description: t('tradesafe.reasons.speed.description')
},
{
icon: <Shield className="w-8 h-8" />,
text: t('tradesafe.reasons.reliability.text'),
description: t('tradesafe.reasons.reliability.description')
},
{
icon: <Globe className="w-8 h-8" />,
text: t('tradesafe.reasons.connection.text'),
description: t('tradesafe.reasons.connection.description')
},
{
icon: <MessageSquare className="w-8 h-8" />,
text: t('tradesafe.reasons.communication.text'),
description: t('tradesafe.reasons.communication.description')
},
{
icon: <Clock className="w-8 h-8" />,
text: t('tradesafe.reasons.time.text'),
description: t('tradesafe.reasons.time.description')
},
{
icon: <CheckCircle className="w-8 h-8" />,
text: t('tradesafe.reasons.solutions.text'),
description: t('tradesafe.reasons.solutions.description')
}
];
const [expandedCards, setExpandedCards] = useState({});
const [hoveredCard, setHoveredCard] = useState(null);
const [page, setPage] = useState(0);
const startIndex = page * CARDS_PER_PAGE;
const endIndex = startIndex + CARDS_PER_PAGE;
const visibleServices = servicesData.slice(startIndex, endIndex);
const totalPages = Math.ceil(servicesData.length / CARDS_PER_PAGE);
const toggleCard = (cardId) => {
setExpandedCards(prev => ({
...prev,
[cardId]: !prev[cardId]
}));
};
const toggleAllCards = () => {
const allExpanded = Object.values(expandedCards).every(Boolean);
const newState = {};
visibleServices.forEach(service => {
newState[service.id] = !allExpanded;
});
setExpandedCards(newState);
};
const handleNextPage = () => {
const newExpandedState = {};
visibleServices.forEach(service => {
newExpandedState[service.id] = false;
});
setExpandedCards(newExpandedState);
setPage((prev) => (prev + 1) % totalPages);
};
const handlePrevPage = () => {
const newExpandedState = {};
visibleServices.forEach(service => {
newExpandedState[service.id] = false;
});
setExpandedCards(newExpandedState);
setPage((prev) => (prev - 1 + totalPages) % totalPages);
};
useEffect(() => {
const newExpandedState = {};
visibleServices.forEach(service => {
newExpandedState[service.id] = expandedCards[service.id] || false;
});
setExpandedCards(newExpandedState);
}, [page]);
const openPdfPresentation = () => {
const pdfUrl = `${window.location.origin}/trader-safe.pdf`;
window.open(pdfUrl, "_blank", "noopener,noreferrer");
};
const openPlatformLink = () => {
const platformUrl = "http://45.93.137.91/";
window.open(platformUrl, "_blank", "noopener,noreferrer");
};
if (!ready) return (
<div className="flex justify-center items-center h-screen bg-gradient-to-br from-[#23558f] via-[#3360b2] to-[#3c5ee3]">
<div className="animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-white"></div>
</div>
);
return (
<>
<Element name="services">
<motion.section
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.8 }}
className="w-full min-h-screen py-12 px-4 sm:px-6 text-gray-800 flex flex-col items-center font-sans relative overflow-hidden"
style={{
direction: "rtl",
background: "linear-gradient(135deg, #dceafe 0%, #e8f4ff 25%, #c6e2ff 50%, #a3d0ff 75%, #23558f 100%)"
}}
>
<div className="absolute inset-0 overflow-hidden">
<div className="absolute -top-40 -right-40 w-80 h-80 bg-[#3c5ee3] rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-pulse"></div>
<div className="absolute -bottom-40 -left-40 w-80 h-80 bg-[#2ecc71] rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-pulse delay-1000"></div>
<div className="absolute top-1/2 left-1/3 w-60 h-60 bg-[#9b59b6] rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-pulse delay-500"></div>
<div className="absolute top-0 left-0 w-full h-32 bg-gradient-to-b from-[#23558f]/30 to-transparent"></div>
<div className="absolute bottom-0 left-0 w-full h-32 bg-gradient-to-t from-[#3c5ee3]/30 to-transparent"></div>
</div>
<div className="relative z-10 w-full max-w-7xl mx-auto">
<motion.div
initial={{ y: -50, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.6 }}
className="text-center mb-8"
>
<h1 className="pt-6 mb-4 text-4xl font-extrabold md:text-5xl lg:text-6xl">
<motion.span
className="bg-clip-text text-transparent bg-gradient-to-r from-[#2d59b3] via-blue-200 to-[#32a896]"
animate={{
backgroundPosition: ["0% 50%", "100% 50%", "0% 50%"]
}}
transition={{
duration: 5,
repeat: Infinity,
ease: "linear"
}}
style={{
backgroundSize: "200% 100%"
}}
>
{t('tradesafe.services.title')}
</motion.span>
</h1>
<p className="text-lg font-medium text-gray-700 lg:text-xl mb-6 max-w-3xl mx-auto">
{t('tradesafe.subtitle')}
</p>
<div className="flex justify-center mb-8">
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
onClick={toggleAllCards}
className="px-6 py-3 bg-gradient-to-r from-[#23558f] to-[#3c5ee3] text-white font-semibold rounded-full shadow-lg hover:shadow-xl transition-all duration-300 flex items-center gap-2"
>
{Object.values(expandedCards).every(Boolean) ? (
<>
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 15l7-7 7 7" />
</svg>
{t('tradesafe.buttons.collapseAll')}
</>
) : (
<>
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
{t('tradesafe.buttons.showDetails')}
</>
)}
</motion.button>
</div>
</motion.div>
<div className="w-full px-4 relative z-10">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
<AnimatePresence>
{visibleServices.map((service, index) => {
const isExpanded = expandedCards[service.id] || false;
const isHovered = hoveredCard === service.id;
return (
<motion.div
key={service.id}
initial={{ scale: 0.9, opacity: 0, y: 20 }}
animate={{
scale: 1,
opacity: 1,
y: 0,
}}
exit={{ scale: 0.9, opacity: 0, y: -20 }}
transition={{
duration: 0.4,
delay: index * 0.1,
type: "spring",
stiffness: 100
}}
whileHover={{
y: -5,
transition: { duration: 0.2 }
}}
onHoverStart={() => setHoveredCard(service.id)}
onHoverEnd={() => setHoveredCard(null)}
onClick={() => toggleCard(service.id)}
className={`relative cursor-pointer transition-all duration-300 ease-in-out p-6 rounded-2xl shadow-lg backdrop-blur-sm bg-white/90 border-2 ${
isExpanded
? 'border-[#3c5ee3] shadow-xl'
: 'border-white/20 hover:border-[#3c5ee3]/30'
}`}
>
<div className={`absolute inset-0 rounded-2xl ${service.bgColor} opacity-20`}></div>
<div className="relative z-10 h-full flex flex-col">
<div className="flex items-center justify-between mb-4">
<div className={`p-3 rounded-xl bg-gradient-to-br ${service.color} text-white shadow-lg`}>
{service.icon}
</div>
<motion.div
animate={{ rotate: isExpanded ? 180 : 0 }}
transition={{ duration: 0.3 }}
className="w-6 h-6 text-gray-500"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</motion.div>
</div>
<div className="flex-1">
<h3 className="text-xl font-bold text-gray-800 mb-2">
{service.title}
</h3>
<p className="text-gray-600 text-sm mb-4">
{service.description}
</p>
<AnimatePresence>
{isExpanded && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3 }}
className="overflow-hidden"
>
<div className="pt-4 border-t border-gray-200">
<p className="text-gray-700 text-sm mb-3 leading-relaxed">
{service.details}
</p>
<div className="flex flex-wrap gap-2">
{Array.isArray(service.features) && service.features.map((feature, idx) => (
<motion.span
key={idx}
initial={{ scale: 0.8, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ delay: idx * 0.05 }}
className="px-3 py-1 bg-gradient-to-r from-white to-gray-50 text-[#23558f] text-xs font-medium rounded-full border border-[#23558f]/20 shadow-sm"
>
{feature}
</motion.span>
))}
</div>
</div>
</motion.div>
)}
</AnimatePresence>
<AnimatePresence>
{!isExpanded && isHovered && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.2 }}
className="overflow-hidden"
>
<div className="pt-3 border-t border-dashed border-gray-300 mt-3">
<p className="text-gray-700 text-xs mb-2 line-clamp-2">
{service.details.split(' - ')[0]}
</p>
<div className="flex flex-wrap gap-1">
{Array.isArray(service.features) && service.features.slice(0, 2).map((feature, idx) => (
<span
key={idx}
className="px-2 py-1 bg-gradient-to-r from-[#dceafe] to-[#e8f4ff] text-[#23558f] text-xs font-medium rounded-full"
>
{feature}
</span>
))}
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
</div>
{isHovered && !isExpanded && (
<motion.div
className="absolute inset-0 rounded-2xl bg-gradient-to-br from-[#3c5ee3]/5 to-transparent"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
)}
{isExpanded && (
<motion.div
className="absolute inset-0 rounded-2xl bg-gradient-to-br from-[#3c5ee3]/10 to-transparent"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
/>
)}
</motion.div>
);
})}
</AnimatePresence>
</div>
<div className="flex justify-center items-center gap-6 mt-12">
<motion.button
whileHover={{ scale: 1.05, x: -5 }}
whileTap={{ scale: 0.95 }}
onClick={handlePrevPage}
className="p-4 rounded-full bg-gradient-to-r from-[#23558f] to-[#3360b2] text-white shadow-lg hover:shadow-xl transition-all duration-300"
>
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</motion.button>
<div className="flex gap-3">
{Array.from({ length: totalPages }).map((_, idx) => (
<motion.button
key={idx}
whileHover={{ scale: 1.2 }}
whileTap={{ scale: 0.9 }}
onClick={() => {
const newExpandedState = {};
visibleServices.forEach(service => {
newExpandedState[service.id] = false;
});
setExpandedCards(newExpandedState);
setPage(idx);
}}
className={`w-10 h-10 rounded-full flex items-center justify-center font-medium transition-all ${
page === idx
? 'bg-gradient-to-r from-[#3c5ee3] to-[#2ecc71] text-white shadow-lg scale-110'
: 'bg-white/80 text-gray-600 hover:bg-white'
}`}
>
{idx + 1}
</motion.button>
))}
</div>
<motion.button
whileHover={{ scale: 1.05, x: 5 }}
whileTap={{ scale: 0.95 }}
onClick={handleNextPage}
className="p-4 rounded-full bg-gradient-to-r from-[#23558f] to-[#3360b2] text-white shadow-lg hover:shadow-xl transition-all duration-300"
>
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</motion.button>
</div>
<div className="text-center mt-4">
<span className="text-gray-600 font-medium">
{t('tradesafe.buttons.page', { current: page + 1, total: totalPages })}
</span>
</div>
</div>
</div>
</motion.section>
</Element>
<Element name="why-us">
<motion.section
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
transition={{ duration: 0.8 }}
viewport={{ once: true }}
className="w-full py-16 px-4 sm:px-6 text-gray-800 flex flex-col items-center font-sans relative overflow-hidden"
style={{
direction: "rtl",
background: "linear-gradient(135deg, #dceafe 0%, #e8f4ff 25%, #c6e2ff 50%, #a3d0ff 75%, #23558f 100%)"
}}
>
<div className="absolute inset-0 bg-white/90"></div>
<div className="absolute inset-0 overflow-hidden">
<div className="absolute -top-40 -right-40 w-80 h-80 bg-[#3c5ee3] rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-pulse"></div>
<div className="absolute -bottom-40 -left-40 w-80 h-80 bg-[#2ecc71] rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-pulse delay-1000"></div>
<div className="absolute top-1/2 left-1/3 w-60 h-60 bg-[#9b59b6] rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-pulse delay-500"></div>
<div className="absolute top-0 left-0 w-full h-32 bg-gradient-to-b from-[#23558f]/30 to-transparent"></div>
<div className="absolute bottom-0 left-0 w-full h-32 bg-gradient-to-t from-[#3c5ee3]/30 to-transparent"></div>
</div>
<div className="relative z-10 w-full max-w-6xl mx-auto">
<motion.h1
initial={{ y: -30, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.6 }}
className="pt-6 mb-12 text-4xl font-extrabold md:text-5xl lg:text-6xl text-center"
>
<motion.span
className="bg-clip-text text-transparent bg-gradient-to-r from-[#2d59b3] via-blue-200 to-[#32a896]"
animate={{
backgroundPosition: ["0% 50%", "100% 50%", "0% 50%"]
}}
transition={{
duration: 5,
repeat: Infinity,
ease: "linear"
}}
style={{
backgroundSize: "200% 100%"
}}
>
{t('tradesafe.reasons.title')}
</motion.span>
</motion.h1>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 px-4">
{reasonsToChooseUs.map((reason, index) => (
<motion.div
key={index}
initial={{ y: 50, opacity: 0, scale: 0.9 }}
whileInView={{ y: 0, opacity: 1, scale: 1 }}
transition={{
duration: 0.5,
delay: index * 0.1,
type: "spring",
stiffness: 100
}}
whileHover={{
y: -8,
scale: 1.02,
transition: { duration: 0.2 }
}}
className="group relative bg-white/95 backdrop-blur-sm p-6 rounded-2xl shadow-lg border border-gray-100 hover:border-[#3c5ee3]/50 hover:shadow-2xl transition-all duration-300"
>
<div className="flex items-start gap-4">
<motion.div
whileHover={{ rotate: [0, -10, 10, 0] }}
transition={{ duration: 0.5 }}
className={`p-3 rounded-xl bg-gradient-to-br ${
index % 3 === 0 ? 'from-[#23558f] to-[#3360b2]' :
index % 3 === 1 ? 'from-[#3c5ee3] to-[#5c7ce3]' :
'from-[#2ecc71] to-[#1abc9c]'
} text-white shadow-lg`}
>
{reason.icon}
</motion.div>
<div className="flex-1">
<h3 className="text-lg font-bold text-gray-800 mb-2">
{reason.text}
</h3>
<p className="text-gray-600 text-sm leading-relaxed">
{reason.description}
</p>
</div>
</div>
<motion.div
className="absolute inset-0 rounded-2xl bg-gradient-to-br from-[#3c5ee3]/0 via-[#3c5ee3]/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500"
initial={false}
/>
<motion.div
className="absolute bottom-0 left-1/2 h-1 w-0 group-hover:w-3/4 bg-gradient-to-r from-transparent via-[#3c5ee3] to-transparent rounded-full"
initial={{ x: "-50%", width: "0%" }}
whileHover={{ width: "75%" }}
transition={{ duration: 0.3 }}
/>
</motion.div>
))}
</div>
<motion.div
initial={{ opacity: 0, scale: 0.9, y: 30 }}
whileInView={{ opacity: 1, scale: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.3 }}
className="mt-16 p-8 rounded-2xl shadow-2xl text-center relative overflow-hidden"
style={{
background: "linear-gradient(135deg, #23558f 0%, #3360b2 33%, #3c5ee3 66%, #2ecc71 100%)"
}}
>
<div className="absolute inset-0">
<div className="absolute top-0 right-0 w-32 h-32 bg-white/10 rounded-full blur-2xl"></div>
<div className="absolute bottom-0 left-0 w-32 h-32 bg-white/10 rounded-full blur-2xl"></div>
</div>
<div className="relative z-10">
<h3 className="text-2xl md:text-3xl font-bold text-white mb-4">
{t('tradesafe.reasons.cta.title')}
</h3>
<p className="text-white/90 text-lg mb-6 max-w-2xl mx-auto">
{t('tradesafe.reasons.cta.subtitle')}
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<motion.button
whileHover={{
scale: 1.05,
boxShadow: "0 10px 25px rgba(0,0,0,0.2)"
}}
whileTap={{ scale: 0.95 }}
onClick={openPlatformLink}
className="px-8 py-3 bg-white text-[#23558f] font-bold rounded-full shadow-lg hover:shadow-xl transition-all duration-300 flex items-center justify-center gap-2"
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
/>
</svg>
{t('tradesafe.buttons.startNow')}
</motion.button>
<motion.button
whileHover={{
scale: 1.05,
boxShadow: "0 10px 25px rgba(255,255,255,0.2)"
}}
whileTap={{ scale: 0.95 }}
onClick={openPdfPresentation}
className="px-8 py-3 bg-transparent border-2 border-white text-white font-bold rounded-full hover:bg-white/10 transition-all duration-300 flex items-center justify-center gap-2"
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
/>
</svg>
{t('tradesafe.buttons.viewPresentation')}
</motion.button>
</div>
</div>
</motion.div>
</div>
</motion.section>
</Element>
</>
);
};
export default Services;