| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- import React, { useState } from "react";
- import { Area, Package } from "../services/product/type";
- import { useTranslation } from "react-i18next";
- interface ProductInfoModalProps {
- isOpen: boolean;
- onClose: () => void;
- packageInfo: Package | null;
- }
- const ProductInfoModal: React.FC<ProductInfoModalProps> = ({
- isOpen,
- onClose,
- packageInfo,
- }) => {
- const { t } = useTranslation();
- const [activeTab, setActiveTab] = useState<"specs" | "notes">("specs");
- if (!isOpen || !packageInfo) return null;
- const specs = [
- {
- label: t("coverageArea"),
- value: packageInfo?.coverageArea,
- icon: (
- <svg
- className="w-5 h-5 color-EE0434"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0"
- />
- </svg>
- ),
- },
- {
- label: t("networkProvider"),
- value: packageInfo?.carriers,
- icon: (
- <svg
- className="w-5 h-5 color-EE0434"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"
- />
- </svg>
- ),
- },
- {
- label: t("infoRegistration") + " (eKYC)",
- value: packageInfo?.ekycRequired ? t("required") : t("notRequired"),
- icon: (
- <svg
- className="w-5 h-5 color-EE0434"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
- />
- </svg>
- ),
- },
- {
- label: t("activationMethod"),
- value:
- packageInfo?.activationMethod === 1
- ? t("usageTimeCalculatedFromSignal")
- : t("usageTimeCalculatedFromPurchase"),
- icon: (
- <svg
- className="w-5 h-5 color-EE0434"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M12 4v1m6 11h2m-6 0h-2v4m0-11v3m0 0h.01M12 14.5V12m0 0V8.832c0-1.12 1.682-1.43 2.182-1.832l.75-1.05a.5.5 0 00-.864-.53l-1.07 1.635M12 21a9 9 0 110-18 9 9 0 010 18z"
- />
- </svg>
- ),
- },
- {
- label: t("deliveryMethod"),
- value:
- "Bạn sẽ nhận được email chứa eSIM trong vòng 5 phút sau khi thanh toán thành công. ",
- // packageInfo?.deliveryMethod === 0
- // ? t(
- // "youWillReceiveAnEmailImmediatelyAfterPaymentWithEsimWaitForShippingAndReceiveYourPhysicalSim",
- // )
- // : t("physicalSimWillBeShippedToYourAddressWithin3-5BusinessDays")
- icon: (
- <svg
- className="w-5 h-5 color-EE0434"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path d="M9 17a2 2 0 11-4 0 2 2 0 014 0zM19 17a2 2 0 11-4 0 2 2 0 014 0z" />
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M13 16V6a1 1 0 00-1-1H4a1 1 0 00-1 1v10a1 1 0 001 1h1m8-1a1 1 0 01-1 1H9m4-1V8a1 1 0 011-1h2.586a1 1 0 01.707.293l3.414 3.414a1 1 0 01.293.707V16a1 1 0 01-1 1h-1m-6-1a1 1 0 001 1h1M5 17a2 2 0 10-4 0 2 2 0 004 0zm10 0a2 2 0 10-4 0 2 2 0 004 0z"
- />
- </svg>
- ),
- },
- {
- label: t("phoneNumber"),
- value: packageInfo?.phoneNumber != 0 ? packageInfo.phoneNumber : "No",
- icon: (
- <svg
- className="w-5 h-5 color-EE0434"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"
- />
- </svg>
- ),
- },
- {
- label: t("wifiHotspot"),
- value: packageInfo?.wifiSharing === 1 ? t("yesSupported") : t("no"),
- icon: (
- <svg
- className="w-5 h-5 color-EE0434"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0"
- />
- </svg>
- ),
- },
- {
- label: t("networkTechnology"),
- value: packageInfo?.networkTechnology,
- icon: (
- <svg
- className="w-5 h-5 color-EE0434"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
- />
- </svg>
- ),
- },
- {
- label: t("packageStartTime"),
- value:
- packageInfo?.activationMethod === 1
- ? t("usageTimeCalculatedFromSignal")
- : t("usageTimeCalculatedFromPurchase"),
- icon: (
- <svg
- className="w-5 h-5 color-EE0434"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
- />
- </svg>
- ),
- },
- {
- label: t("dataResetTime"),
- value:
- // 0: Một ngày được tính đến 23:59 Giờ địa phương
- // 1:Gói được tính theo giờ Trung Quốc (UTC+8), nhưng sẽ reset vào 0:00 theo giờ quốc tế UTC+0.
- // 2: Gói được tính theo ngày (0h–24h) của múi giờ quốc gia nơi gói cước được kích hoạt.
- // 3: Một ngày được tính đến 23:59 giờ Bắc Kinh (GMT+8).
- // 4: Thời gian tính theo múi giờ UTC+0, reset lúc 0:00.
- // 5: Một ngày được tính đến 23:59 giờ Bắc Kinh (GMT+8)
- // 6: Thời gian tính theo ngày (0h–24h) của múi giờ quốc gia nơi kích hoạt gói.
- packageInfo?.dataResetTime === 0
- ? "Một ngày được tính đến 23:59 Giờ địa phương."
- : packageInfo?.dataResetTime === 1
- ? "Gói được tính theo giờ Trung Quốc (UTC+8), nhưng sẽ reset vào 0:00 theo giờ quốc tế UTC+0."
- : packageInfo?.dataResetTime === 2
- ? "Gói được tính theo ngày (0h–24h) của múi giờ quốc gia nơi gói cước được kích hoạt."
- : packageInfo?.dataResetTime === 3
- ? "Một ngày được tính đến 23:59 giờ Bắc Kinh (GMT+8)."
- : packageInfo?.dataResetTime === 4
- ? "Thời gian tính theo múi giờ UTC+0, reset lúc 0:00."
- : packageInfo?.dataResetTime === 5
- ? "Một ngày được tính đến 23:59 giờ Bắc Kinh (GMT+8)."
- : packageInfo?.dataResetTime === 6
- ? "Thời gian tính theo ngày (0h–24h) của múi giờ quốc gia nơi kích hoạt gói."
- : "",
- icon: (
- <svg
- className="w-5 h-5 color-EE0434"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
- />
- </svg>
- ),
- },
- {
- label: t("unlimitedPolicy"),
- value: packageInfo?.unlimitedPolicy,
- icon: (
- <svg
- className="w-5 h-5 color-EE0434"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M13 10V3L4 14h7v7l9-11h-7z"
- />
- </svg>
- ),
- },
- {
- label: t("appSupport"),
- value: packageInfo?.appSupport,
- icon: (
- <svg
- className="w-5 h-5 color-EE0434"
- 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>
- ),
- },
- ];
- return (
- <div className="fixed inset-0 z-[100] flex items-center justify-center p-4 animate-in fade-in duration-200">
- <div
- className="absolute inset-0 bg-slate-900/60 backdrop-blur-sm"
- onClick={onClose}
- ></div>
- <div className="relative bg-white rounded-[32px] w-full max-w-2xl max-h-[85vh] shadow-2xl flex flex-col overflow-hidden">
- {/* Header */}
- <div className="p-6 pb-2 border-b border-slate-100 flex justify-between items-center bg-white z-10">
- <h2 className="text-xl md:text-2xl font-black text-slate-800">
- {t("productInformation")}
- </h2>
- <button
- onClick={onClose}
- className="p-2 text-slate-400 hover:text-slate-600 hover:bg-slate-50 rounded-full transition-all"
- >
- <svg
- className="w-6 h-6"
- fill="none"
- stroke="currentColor"
- viewBox="0 0 24 24"
- >
- <path
- strokeLinecap="round"
- strokeLinejoin="round"
- strokeWidth={2}
- d="M6 18L18 6M6 6l12 12"
- />
- </svg>
- </button>
- </div>
- {/* Tabs */}
- <div className="flex px-6 border-b border-slate-100 bg-white z-10">
- <button
- onClick={() => setActiveTab("specs")}
- className={`flex-1 py-4 text-sm md:text-base font-bold text-center border-b-2 transition-colors ${
- activeTab === "specs"
- ? "border-[#EE0434] text-[#EE0434]"
- : "border-transparent text-slate-400 hover:text-slate-600"
- }`}
- >
- {t("specifications")}
- </button>
- <button
- onClick={() => setActiveTab("notes")}
- className={`flex-1 py-4 text-sm md:text-base font-bold text-center border-b-2 transition-colors ${
- activeTab === "notes"
- ? "border-[#EE0434] text-[#EE0434]"
- : "border-transparent text-slate-400 hover:text-slate-600"
- }`}
- >
- {t("notes")}
- </button>
- </div>
- {/* Content */}
- <div className="flex-1 overflow-y-auto p-6 md:p-8 custom-scrollbar bg-white">
- {activeTab === "specs" ? (
- <div className="space-y-6">
- {specs.map((spec, idx) => (
- <div key={idx} className="flex items-start space-x-4">
- <div className="w-6 h-6 text-[#0091ff] shrink-0 mt-0.5">
- {spec.icon}
- </div>
- <div className="flex-1">
- <p className="font-bold text-slate-600 text-sm mb-1">
- {spec.label}:
- </p>
- <p className="text-slate-800 font-medium text-sm md:text-base leading-relaxed">
- {spec.value}
- </p>
- </div>
- </div>
- ))}
- </div>
- ) : (
- <div className="space-y-4 text-slate-600">
- <p className="font-medium leading-relaxed">
- <span className="font-bold text-[16px] color-EE0434">1.</span>{" "}
- {t("note1")}
- </p>
- <p className="font-medium leading-relaxed">
- <span className="font-bold text-[16px] color-EE0434">2.</span>{" "}
- {t("note2")}
- </p>
- <p className="font-medium leading-relaxed">
- <span className="font-bold text-[16px] color-EE0434">3.</span>{" "}
- {t("note3")}
- </p>
- <p className="font-medium leading-relaxed">
- <span className="font-bold text-[16px] color-EE0434">4.</span>{" "}
- {t("note4")}
- </p>
- <p className="font-medium leading-relaxed">
- <span className="font-bold text-[16px] color-EE0434">5.</span>{" "}
- {/* display html */}
- <span dangerouslySetInnerHTML={{ __html: t("note5") }} />
- </p>
- <p className="font-medium leading-relaxed">
- <span className="font-bold text-[16px] color-EE0434">6.</span>{" "}
- {t("note6")}
- </p>
- </div>
- )}
- </div>
- {/* Bottom Fade */}
- <div className="absolute bottom-0 left-0 right-0 h-12 bg-gradient-to-t from-white to-transparent pointer-events-none"></div>
- </div>
- </div>
- );
- };
- export default ProductInfoModal;
|