| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- import React, { useState, useEffect, useCallback } from "react";
- import { useNavigate, useSearchParams } from "react-router-dom";
- import { SimProduct } from "../../services/types";
- import HomeBanner from "./components/HomeBanner";
- import HomeTestimonial from "./components/HomeTestimonial";
- import HomeProduct from "./components/HomeProduct";
- import HomeSearch from "./components/HomeSearch";
- import HomeFaq from "./components/HomeFaq";
- import { useAppDispatch } from "../../hooks/useRedux";
- import { openPopup } from "../../features/popup/popupSlice";
- import partner1 from "../../assets/img/partner1.png";
- import partner2 from "../../assets/img/partner2.png";
- import { authApi } from "../../apis/authApi";
- import { accountLogin } from "../../features/account/accuntSlice";
- import { useTranslation } from "react-i18next";
- import i18n from "../../i18n";
- const HomeView: React.FC = () => {
- const [simType, setSimType] = useState<"eSIM" | "Physical">("eSIM");
- const [searchParams] = useSearchParams();
- const navigate = useNavigate();
- const dispatch = useAppDispatch();
- const { t } = useTranslation();
- const langNow = localStorage.getItem("lang") || "en";
- useEffect(() => {
- // set language in i18n
- i18n.changeLanguage(langNow);
- localStorage.setItem("lang", langNow);
- }, [langNow]);
- useEffect(() => {
- const params = new URLSearchParams(window.location.search);
- console.log("URL Params: ", params.toString());
- const status = params.get("vpc_TxnResponseCode");
- console.log("searchParams: ", searchParams.toString());
- // google callback
- const code = searchParams.get("code");
- if (status) {
- console.log("URL Params:", params);
- if (status === "0") {
- dispatch(
- openPopup({
- isSuccess: true,
- message: t("paymentSuccess"),
- title: t("paymentStatus"),
- buttonText: t("close"),
- hasRightButton: true,
- rightButtonText: t("viewOrder"),
- rightButtonAction: "OPEN_ORDER_HISTORY",
- }),
- );
- } else {
- dispatch(
- openPopup({
- isSuccess: false,
- message: t("paymentFailed"),
- title: t("paymentStatus"),
- buttonText: t("close"),
- }),
- );
- }
- } else if (code) {
- console.log("Handling Google callback with code:", code);
- handleGoogleCallback(code);
- }
- }, []);
- const handleGoogleCallback = async (code: string) => {
- try {
- const response = await authApi.googleCallback({ code });
- if (response.errorCode === "0") {
- dispatch(accountLogin(response.data));
- navigate("/");
- } else {
- console.error("Google callback failed:", response.message);
- }
- } catch (error) {
- console.error("Google callback error:", error);
- }
- };
- const steps = [
- {
- number: "1",
- title: t("compatibleDevice"),
- description: t("checkIfYourPhoneSupportsESIMTechnology"),
- },
- {
- number: "2",
- title: t("pickPlan"),
- description: t("selectADataPackageForYourDestination"),
- },
- {
- number: "3",
- title: t("instantActivation"),
- description: t("scanTheQRCodeAndConnectToHighSpeedData"),
- },
- ];
- return (
- <div className="bg-white overflow-x-hidden">
- <style>{`
- @keyframes marquee-up { 0% { transform: translateY(0); } 100% { transform: translateY(-50%); } }
- @keyframes marquee-down { 0% { transform: translateY(-50%); } 100% { transform: translateY(0); } }
- @keyframes scroll-x { 0% { transform: translateX(0); } 100% { transform: translateX(-33.33%); } }
- @keyframes progress-bar { 0% { width: 0%; } 100% { width: 100%; } }
- .animate-marquee-up { animation: marquee-up 40s linear infinite; }
- .animate-marquee-down { animation: marquee-down 40s linear infinite; }
- .animate-scroll-x { animation: scroll-x 10s linear infinite; }
- .animate-progress { animation: progress-bar 6s linear infinite; }
- `}</style>
- {/* Main Search Section */}
- <HomeSearch />
- {/* Hero Banner */}
- <HomeBanner />
- {/* Product Selection */}
- <HomeProduct />
- {/* Customer Testimonials */}
- <HomeTestimonial />
- {/* WHY CHOOSE INFIGATE */}
- <section className="py-16 md:py-24 bg-white px-4">
- <div className="max-w-7xl mx-auto">
- <h2 className="text-3xl md:text-6xl font-black text-center mb-12 md:mb-20 tracking-tight text-slate-900">
- <span className="text-[#EE0434]">{t("chooseGetgo")}</span>
- </h2>
- <div className="bg-gradient-to-br from-[#E21c34] to-[#500B28] rounded-[32px] md:rounded-[60px] p-8 md:p-16 lg:p-24 shadow-2xl relative overflow-hidden">
- <div className="absolute top-0 right-0 w-[500px] h-[500px] bg-white/5 rounded-full blur-[100px] -translate-y-1/2 translate-x-1/2"></div>
- <div className="absolute bottom-0 left-0 w-[300px] h-[300px] bg-black/10 rounded-full blur-[80px] translate-y-1/2 -translate-x-1/2"></div>
- <div className="grid grid-cols-1 md:grid-cols-2 gap-12 md:gap-x-20 md:gap-y-16 relative z-10">
- <div className="space-y-6">
- <div className="flex items-center space-x-4">
- <div className="w-12 h-12 md:w-16 md:h-16 rounded-full bg-white/20 flex items-center justify-center shrink-0 border border-white/10 shadow-lg backdrop-blur-sm">
- <svg
- className="w-6 h-6 md:w-8 md:h-8 text-white"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M13 10V3L4 14h7v7l9-11h-7z"
- />
- </svg>
- </div>
- <h3 className="text-lg md:text-2xl font-black text-white leading-tight">
- {t("fastCost")}
- </h3>
- </div>
- <ul className="space-y-4 text-sm md:text-lg text-white/90 list-disc pl-6 marker:text-red-200">
- <li>{t("internationalTravelStarts")}</li>
- <li>{t("easilyChooseSuitableSim")}</li>
- <li>{t("eSIMReceiveQR")}</li>
- <li>{t("physicalSIMDelivery")}</li>
- </ul>
- </div>
- <div className="space-y-6">
- <div className="flex items-center space-x-4">
- <div className="w-12 h-12 md:w-16 md:h-16 rounded-full bg-white/20 flex items-center justify-center shrink-0 border border-white/10 shadow-lg backdrop-blur-sm">
- <svg
- className="w-6 h-6 md:w-8 md:h-8 text-white"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9"
- />
- </svg>
- </div>
- <h3 className="text-lg md:text-2xl font-black text-white leading-tight">
- {t("globalAnywhere")}
- </h3>
- </div>
- <ul className="space-y-4 text-sm md:text-lg text-white/90 list-disc pl-6 marker:text-red-200">
- <li>{t("fastestData")}</li>
- <li>{t("worldLeadingNetwork")}</li>
- <li>{t("flexibleDiversePackages")}</li>
- </ul>
- </div>
- <div className="space-y-6">
- <div className="flex items-center space-x-4">
- <div className="w-12 h-12 md:w-16 md:h-16 rounded-full bg-white/20 flex items-center justify-center shrink-0 border border-white/10 shadow-lg backdrop-blur-sm">
- <svg
- className="w-6 h-6 md:w-8 md:h-8 text-white"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M18.364 5.636l-3.536 3.536m0 5.656l3.536 3.536M9.172 9.172L5.636 5.636m3.536 9.192l-3.536 3.536M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-5 0a4 4 0 11-8 0 4 4 0 018 0z"
- />
- </svg>
- </div>
- <h3 className="text-lg md:text-2xl font-black text-white leading-tight">
- {t("customerSupport")}
- </h3>
- </div>
- <ul className="space-y-4 text-sm md:text-lg text-white/90 list-disc pl-6 marker:text-red-200">
- <li>{t("customerServiceAvailable")}</li>
- <li>{t("supportChannels")}</li>
- </ul>
- </div>
- <div className="space-y-6">
- <div className="flex items-center space-x-4">
- <div className="w-12 h-12 md:w-16 md:h-16 rounded-full bg-white/20 flex items-center justify-center shrink-0 border border-white/10 shadow-lg backdrop-blur-sm">
- <svg
- className="w-6 h-6 md:w-8 md:h-8 text-white"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
- />
- </svg>
- </div>
- <h3 className="text-lg md:text-2xl font-black text-white leading-tight">
- {t("customerPolicy")}
- </h3>
- </div>
- <ul className="space-y-4 text-sm md:text-lg text-white/90 list-disc pl-6 marker:text-red-200">
- <li>{t("refundDefective")}</li>
- <li>{t("commitmentPeaceOfMind")}</li>
- </ul>
- </div>
- </div>
- </div>
- </div>
- </section>
- {/* PARTNERSHIP */}
- <section className="py-12 md:py-20 bg-white px-4">
- <div className="max-w-7xl mx-auto space-y-10 md:space-y-16">
- <h2 className="text-3xl md:text-6xl font-black text-center tracking-tight text-slate-900">
- SkySimHub <span className="text-[#EE0434]">{t("getgoWith")}</span>
- </h2>
- <div className="space-y-8 md:space-y-12 max-w-5xl mx-auto">
- <div className="space-y-4 md:space-y-6">
- <div className="flex items-center space-x-3">
- <div className="w-5 h-5 md:w-6 md:h-6 bg-[#EE0434] rounded-full flex items-center justify-center shrink-0">
- <svg
- className="w-3 h-3 md:w-4 md:h-4 text-white"
- fill="currentColor"
- viewBox="0 0 20 20"
- >
- <path
- fillRule="evenodd"
- d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
- clipRule="evenodd"
- />
- </svg>
- </div>
- <p className="text-sm md:text-2xl font-semibold text-slate-500">
- {t("partnershipNetwork")}
- </p>
- </div>
- <div className="flex flex-wrap gap-3 md:gap-8 justify-center lg:justify-start">
- <div className="bg-white border border-[#EE0434]/20 rounded-xl px-4 py-2 w-36 md:w-56 h-14 flex items-center justify-center shadow-sm">
- <img
- src="https://skysimhub.vn/assets/partners/1.png"
- className="max-h-full max-w-full object-contain"
- />
- </div>
- <div className="bg-white border border-[#EE0434]/20 rounded-xl px-4 py-2 w-36 md:w-56 h-14 flex items-center justify-center shadow-sm">
- <img
- src="https://skysimhub.vn/assets/partners/2.png"
- className="max-h-full max-w-full object-contain"
- />
- </div>
- <div className="bg-white border border-[#EE0434]/20 rounded-xl px-4 py-2 w-36 md:w-56 h-14 flex items-center justify-center shadow-sm">
- <img
- src="https://skysimhub.vn/assets/partners/3.png"
- className="max-h-full max-w-full object-contain"
- />
- </div>
- <div className="bg-white border border-[#EE0434]/20 rounded-xl px-4 py-2 w-36 md:w-56 h-14 flex items-center justify-center shadow-sm">
- <img
- src="https://skysimhub.vn/assets/partners/4.png"
- className="max-h-full max-w-full object-contain"
- />
- </div>
- <div className="bg-white border border-[#EE0434]/20 rounded-xl px-4 py-2 w-36 md:w-56 h-14 flex items-center justify-center shadow-sm">
- <img
- src="https://skysimhub.vn/assets/partners/5.png"
- className="max-h-full max-w-full object-contain"
- />
- </div>
- <div className="bg-white border border-[#EE0434]/20 rounded-xl px-4 py-2 w-36 md:w-56 h-14 flex items-center justify-center shadow-sm">
- <img
- src="https://skysimhub.vn/assets/partners/6.png"
- className="max-h-full max-w-full object-contain"
- />
- </div>
- </div>
- </div>
- </div>
- </div>
- </section>
- {/* How it Works */}
- <section className="py-12 md:py-24 bg-white px-4">
- <div className="max-w-7xl mx-auto">
- <h2 className="text-2xl md:text-6xl font-black text-[#EE0434] text-center mb-6 md:mb-10 tracking-tight leading-tight">
- {t("buyExplore")}
- </h2>
- <div className="flex justify-center mb-10 md:mb-20">
- <div className="inline-flex p-1 bg-slate-100 rounded-full shadow-inner">
- <button
- onClick={() => setSimType("eSIM")}
- className={`px-6 md:px-12 py-2.5 md:py-3 rounded-full text-lg md:text-xs lg:text-xl font-bold transition-all ${
- simType === "eSIM"
- ? "bg-gradient-to-r from-[#E21c34] to-[#500B28] text-white shadow-md"
- : "bg-[#f0f0f0] text-[#8b8e96] hover:text-slate-800"
- }`}
- >
- eSIM
- </button>
- <button
- onClick={() => setSimType("Physical")}
- className={`px-6 md:px-12 py-2.5 md:py-3 rounded-full text-lg md:text-xs lg:text-xl font-bold transition-all ${
- simType === "Physical"
- ? "bg-gradient-to-r from-[#E21c34] to-[#500B28] text-white shadow-md"
- : "bg-[#f0f0f0] text-[#8b8e96] hover:text-slate-800"
- }`}
- >
- {t("physicalSim")}
- </button>
- </div>
- </div>
- <div className="grid grid-cols-1 lg:grid-cols-2 gap-8 md:gap-16 items-center">
- <div className="relative aspect-square bg-[#EE0434]/5 rounded-[24px] md:rounded-[48px] overflow-hidden flex items-center justify-center shadow-xl border border-red-50">
- <div className="absolute inset-0 bg-gradient-to-br from-[#EE0434]/20 to-white/0 opacity-50"></div>
- <div className="w-4/5 h-4/5 relative flex items-center justify-center">
- <svg
- className="w-full h-full text-[#EE0434] drop-shadow-lg"
- viewBox="0 0 100 100"
- fill="none"
- >
- <path
- d="M0 70 Q 25 20, 50 70 T 100 70"
- stroke="currentColor"
- strokeWidth="8"
- strokeLinecap="round"
- className="opacity-80"
- />
- </svg>
- </div>
- </div>
- <div className="space-y-4 md:space-y-12">
- {steps.map((step, index) => (
- <div
- key={index}
- className="flex items-start space-x-4 md:space-x-6 p-4 md:p-8 rounded-[20px] md:rounded-[32px] border bg-transparent border-transparent hover:bg-white hover:shadow-lg hover:border-slate-50 transition-all"
- >
- <span className="text-xl md:text-3xl font-black text-[#EE0434] mt-0.5 shrink-0">
- {step.number}
- </span>
- <div>
- <h3 className="text-base md:text-2xl font-black text-slate-900 mb-0.5 md:mb-2">
- {step.title}
- </h3>
- <p className="text-slate-500 text-[11px] md:text-lg leading-relaxed">
- {step.description}
- </p>
- </div>
- </div>
- ))}
- </div>
- </div>
- </div>
- </section>
- {/* FAQ */}
- <HomeFaq />
- {/* Refund */}
- <section className="py-16 md:py-24 bg-white px-4">
- <div className="max-w-7xl mx-auto flex flex-col items-center">
- <h2 className="text-3xl md:text-[56px] font-black text-center mb-12 md:mb-20 tracking-tight text-slate-900">
- {t("refundDefective")}
- </h2>
- <button className="flex items-center bg-gradient-to-r from-[#E21c34] to-[#500B28] p-2 pr-10 rounded-full shadow-xl hover:scale-105 transition-all">
- <div className="w-16 h-16 bg-white rounded-full flex items-center justify-center text-slate-800">
- <svg
- className="w-8 h-8"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2.5}
- d="M17 8l4 4m0 0l-4 4m4-4H3"
- />
- </svg>
- </div>
- <span className="ml-6 text-white text-2xl font-black">
- {t("returnGuide")}
- </span>
- </button>
- </div>
- </section>
- </div>
- );
- };
- export default HomeView;
|