2
0

2 Komitmen 6e948f735b ... 1e6f5c6aab

Pembuat SHA1 Pesan Tanggal
  trunghieubui 1e6f5c6aab Merge branch 'master' of https://source.viettech.asia/unitel/ESIM 2 minggu lalu
  trunghieubui 771b2d52b4 Refactor order status handling and improve product detail options 2 minggu lalu

+ 27 - 6
EsimLao/docs/skyhub.drawio

@@ -1,6 +1,6 @@
-<mxfile host="Electron" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/29.3.0 Chrome/140.0.7339.249 Electron/38.7.2 Safari/537.36" version="29.3.0">
+<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/29.3.0 Chrome/140.0.7339.249 Electron/38.7.2 Safari/537.36" version="29.3.0">
   <diagram id="kgpKYQtTHZ0yAKxKKP6v" name="Page-1">
-    <mxGraphModel dx="3202" dy="2428" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
+    <mxGraphModel dx="2511" dy="2073" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
       <root>
         <mxCell id="0" />
         <mxCell id="1" parent="0" />
@@ -130,11 +130,11 @@
         <mxCell id="uRcrelpJeVWRNYr8ECgl-48" parent="1" style="outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.worker;fillColor=#D9A741;gradientColor=none;" value="PORTAL" vertex="1">
           <mxGeometry height="63" width="60" x="595" y="430" as="geometry" />
         </mxCell>
-        <mxCell id="uRcrelpJeVWRNYr8ECgl-49" parent="1" style="outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.worker;fillColor=#D9A741;gradientColor=none;" value="ORDER" vertex="1">
-          <mxGeometry height="63" width="60" x="690" y="327" as="geometry" />
+        <mxCell id="uRcrelpJeVWRNYr8ECgl-49" parent="1" style="outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.worker;fillColor=#D9A741;gradientColor=none;" value="CUSTOMER" vertex="1">
+          <mxGeometry height="63" width="60" x="720" y="327" as="geometry" />
         </mxCell>
-        <mxCell id="uRcrelpJeVWRNYr8ECgl-50" parent="1" style="outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.worker;fillColor=#D9A741;gradientColor=none;" value="VOUCHER" vertex="1">
-          <mxGeometry height="63" width="60" x="690" y="430" as="geometry" />
+        <mxCell id="uRcrelpJeVWRNYr8ECgl-50" parent="1" style="outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.worker;fillColor=#D9A741;gradientColor=none;" value="CO&lt;span style=&quot;background-color: transparent; color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&gt;MISSION&lt;/span&gt;" vertex="1">
+          <mxGeometry height="63" width="60" x="720" y="430" as="geometry" />
         </mxCell>
         <mxCell id="uRcrelpJeVWRNYr8ECgl-52" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="&lt;font style=&quot;font-size: 18px;&quot;&gt;CORE&lt;/font&gt;" vertex="1">
           <mxGeometry height="30" width="60" x="760" y="640" as="geometry" />
@@ -285,6 +285,27 @@
         <mxCell id="uRcrelpJeVWRNYr8ECgl-109" parent="1" style="outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.worker;fillColor=#D9A741;gradientColor=none;" value="COMMISSION" vertex="1">
           <mxGeometry height="63" width="60" x="790" y="430" as="geometry" />
         </mxCell>
+        <mxCell id="8LnyclVRHVrttfvcOQKk-8" parent="1" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;elbow&quot;:&quot;vertical&quot;,&quot;curved&quot;:0,&quot;rounded&quot;:0};" value="Customer" vertex="1">
+          <mxGeometry height="510" width="100" x="2130" y="-560" as="geometry" />
+        </mxCell>
+        <mxCell id="8LnyclVRHVrttfvcOQKk-9" parent="8LnyclVRHVrttfvcOQKk-8" style="html=1;points=[[0,0,0,0,5],[0,1,0,0,-5],[1,0,0,0,5],[1,1,0,0,-5]];perimeter=orthogonalPerimeter;outlineConnect=0;targetShapes=umlLifeline;portConstraint=eastwest;newEdgeStyle={&quot;curved&quot;:0,&quot;rounded&quot;:0};fillColor=#808080;" value="" vertex="1">
+          <mxGeometry height="120" width="10" x="45" y="90" as="geometry" />
+        </mxCell>
+        <mxCell id="8LnyclVRHVrttfvcOQKk-10" parent="1" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;elbow&quot;:&quot;vertical&quot;,&quot;curved&quot;:0,&quot;rounded&quot;:0};" value="ESIM" vertex="1">
+          <mxGeometry height="520" width="100" x="1910" y="-560" as="geometry" />
+        </mxCell>
+        <mxCell id="8LnyclVRHVrttfvcOQKk-11" parent="8LnyclVRHVrttfvcOQKk-10" style="html=1;points=[[0,0,0,0,5],[0,1,0,0,-5],[1,0,0,0,5],[1,1,0,0,-5]];perimeter=orthogonalPerimeter;outlineConnect=0;targetShapes=umlLifeline;portConstraint=eastwest;newEdgeStyle={&quot;curved&quot;:0,&quot;rounded&quot;:0};" value="" vertex="1">
+          <mxGeometry height="120" width="10" x="45" y="130" as="geometry" />
+        </mxCell>
+        <mxCell id="8LnyclVRHVrttfvcOQKk-19" parent="1" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;elbow&quot;:&quot;vertical&quot;,&quot;curved&quot;:0,&quot;rounded&quot;:0};" value="Mini APP" vertex="1">
+          <mxGeometry height="520" width="100" x="1700" y="-560" as="geometry" />
+        </mxCell>
+        <mxCell id="8LnyclVRHVrttfvcOQKk-20" parent="8LnyclVRHVrttfvcOQKk-19" style="html=1;points=[[0,0,0,0,5],[0,1,0,0,-5],[1,0,0,0,5],[1,1,0,0,-5]];perimeter=orthogonalPerimeter;outlineConnect=0;targetShapes=umlLifeline;portConstraint=eastwest;newEdgeStyle={&quot;curved&quot;:0,&quot;rounded&quot;:0};" value="" vertex="1">
+          <mxGeometry height="120" width="10" x="45" y="130" as="geometry" />
+        </mxCell>
+        <mxCell id="8LnyclVRHVrttfvcOQKk-23" parent="1" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;text-decoration:underline;&quot;&gt;&lt;b&gt;Login&lt;/b&gt;&lt;/p&gt;&lt;hr size=&quot;1&quot; style=&quot;border-style:solid;&quot;&gt;&lt;p style=&quot;margin:0px;margin-left:8px;&quot;&gt;abx:&amp;nbsp;&lt;/p&gt;" vertex="1">
+          <mxGeometry height="90" width="160" x="1760" y="-410" as="geometry" />
+        </mxCell>
       </root>
     </mxGraphModel>
   </diagram>

+ 0 - 1
EsimLao/esim-vite/src/components/Footer.tsx

@@ -6,7 +6,6 @@ import { Area } from "../services/product/type";
 import { useNavigate } from "react-router-dom";
 const Footer: React.FC = () => {
   const { t } = useTranslation();
-
   const navigate = useNavigate();
 
   return (

+ 1 - 1
EsimLao/esim-vite/src/i18n/locales/en.json

@@ -192,7 +192,7 @@
   "weveSentVerificationCode": "We've sent a 6-digit verification code to",
   "verificationCode": "Verification Code",
   "codeExpiredPleaseRequestNewOne": "Code expired. Please request a new one.",
-  "fastSimpleRed": "Fast. Simple. Red.",
+  "fastSimpleRed": "Fast. Simple.",
   "globalConnectivityForTheModernTraveler": "Global connectivity for the modern traveler.",
   "codeExpiresIn": "Code expires in",
   "enterYourEmail": "Enter your email",

+ 1 - 1
EsimLao/esim-vite/src/i18n/locales/vi.json

@@ -192,7 +192,7 @@
   "weveSentVerificationCode": "Chúng tôi đã gửi mã xác minh gồm 6 chữ số đến",
   "verificationCode": "Mã xác minh",
   "codeExpiredPleaseRequestNewOne": "Mã đã hết hạn. Vui lòng yêu cầu mã mới.",
-  "fastSimpleRed": "Nhanh. Đơn giản. Đỏ.",
+  "fastSimpleRed": "Nhanh. Đơn giản.",
   "globalConnectivityForTheModernTraveler": "Kết nối toàn cầu cho người du lịch hiện đại",
   "codeExpiresIn": "Mã hết hạn sau",
   "enterYourEmail": "Nhập email của bạn",

+ 38 - 8
EsimLao/esim-vite/src/logic/loigicUtils.ts

@@ -10,7 +10,7 @@ export const formatCarriers = (text) => {
 export const setWithExpiry = <T>(
   key: string,
   value: T,
-  ttlMs?: number | null
+  ttlMs?: number | null,
 ) => {
   const now = Date.now();
 
@@ -54,7 +54,7 @@ type CurrencyCode =
 export const formatCurrency = (
   amount: number | string,
   currency?: string,
-  locale?: string
+  locale?: string,
 ) => {
   if (amount === null || amount === undefined || amount === "") return "";
 
@@ -62,15 +62,45 @@ export const formatCurrency = (
 
   const resolvedLocale =
     locale ??
-    (currency === "VND"
-      ? "vi-VN"
-      : currency === "USD"
-        ? "en-US"
-        : "en-GB");
+    (currency === "VND" ? "vi-VN" : currency === "USD" ? "en-US" : "en-GB");
 
   return new Intl.NumberFormat(resolvedLocale, {
     style: "currency",
     currency,
     minimumFractionDigits: currency === "VND" ? 0 : 2,
   }).format(value);
-};
+};
+
+export const convertOrderStatusToText = (status: number) => {
+  //   1: chờ thanh toán
+  // 2: đã thanh toán, chờ xuất esim
+  // 3: thanh toán thất bại
+  // 4: đã trả esim
+  switch (status) {
+    case 1:
+      return "Chờ thanh toán";
+    case 2:
+      return "Đã thanh toán, chờ xuất eSIM";
+    case 3:
+      return "Thanh toán thất bại";
+    case 4:
+      return "Đã trả eSIM";
+    default:
+      return "Không xác định";
+  }
+};
+
+export const convertOrderStatusToColor = (type: number) => {
+  switch (type) {
+    case 1:
+      return "bg-orange-400 text-white";
+    case 2:
+      return "bg-[#00c087] text-white";
+    case 3:
+      return "bg-red-400 text-white";
+    case 4:
+      return "bg-blue-400 text-white";
+    default:
+      return "bg-slate-800 text-white";
+  }
+};

+ 20 - 45
EsimLao/esim-vite/src/pages/order-detail/OrderDetailView.tsx

@@ -10,7 +10,12 @@ import { useMutation } from "@tanstack/react-query";
 import React, { useState, useEffect } from "react";
 import { useLocation, useNavigate } from "react-router-dom";
 import { openQRModal } from "../../features/popup/popupSlice";
-import { formatCurrency, formatNumber } from "../../logic/loigicUtils";
+import {
+  convertOrderStatusToColor,
+  convertOrderStatusToText,
+  formatCurrency,
+  formatNumber,
+} from "../../logic/loigicUtils";
 import { useTranslation } from "react-i18next";
 import { format } from "path";
 
@@ -72,7 +77,7 @@ const OrderDetailView = () => {
             }
 
             return null;
-          })
+          }),
         );
 
         const validResults = results.filter(Boolean);
@@ -101,7 +106,7 @@ const OrderDetailView = () => {
 
     const percentage = Math.min(
       Math.max(dataUsage.usageData / dataUsage.totalData, 0),
-      1
+      1,
     );
     const strokeDashoffset = arcLength - percentage * arcLength;
 
@@ -181,12 +186,12 @@ const OrderDetailView = () => {
           {dataUsage.status === 0
             ? t("notActive")
             : dataUsage.status === 1
-            ? t("active")
-            : dataUsage.status === 2
-            ? t("finished")
-            : dataUsage.status === 3
-            ? t("expired")
-            : t("unknown")}
+              ? t("active")
+              : dataUsage.status === 2
+                ? t("finished")
+                : dataUsage.status === 3
+                  ? t("expired")
+                  : t("unknown")}
         </p>
         {/* <p className="mt-1 text-slate-400 text-sm font-bold uppercase tracking-widest">
           {100 - Math.round((used / total) * 100)}% {t("remaining")}
@@ -195,16 +200,6 @@ const OrderDetailView = () => {
     );
   };
 
-  const getStatusColor = (status: number) => {
-    switch (status) {
-      case 2:
-        return "bg-[#00c087] text-white";
-      case 1:
-        return "bg-orange-400 text-white";
-      default:
-        return "bg-slate-800 text-white";
-    }
-  };
   return (
     <div className="bg-[#fcfdfe] min-h-screen pb-20">
       {/* Breadcrumb */}
@@ -285,31 +280,11 @@ const OrderDetailView = () => {
                   {state.orderHistory?.orderCode}
                 </span>
               </div>
-              {state.orderHistory?.status === 2 ? (
-                <span
-                  className={`px-3 py-1 rounded-md text-sm font-bold shadow-sm ${getStatusColor(
-                    state.orderHistory?.status
-                  )}`}
-                >
-                  {t("paymentSuccessful")}
-                </span>
-              ) : state.orderHistory?.status === 1 ? (
-                <span
-                  className={`px-3 py-1 rounded-md text-sm font-bold shadow-sm ${getStatusColor(
-                    state.orderHistory?.status
-                  )}`}
-                >
-                  {t("pendingPayment")}
-                </span>
-              ) : (
-                <span
-                  className={`px-3 py-1 rounded-md text-sm font-bold shadow-sm ${getStatusColor(
-                    state.orderHistory?.status
-                  )}`}
-                >
-                  {t("failure")}
-                </span>
-              )}
+              <span
+                className={`px-3 py-1 rounded-md text-sm font-bold shadow-sm ${convertOrderStatusToColor(state.orderHistory?.status)}`}
+              >
+                {convertOrderStatusToText(state.orderHistory?.status)}
+              </span>
             </div>
 
             {/* Tabs */}
@@ -342,7 +317,7 @@ const OrderDetailView = () => {
                 {t("totalTotal")}:{" "}
                 {formatCurrency(
                   state.orderHistory?.paymentMoney,
-                  state.orderHistory?.curency
+                  state.orderHistory?.curency,
                 )}{" "}
                 {/* <span className="text-slate-500 font-normal">
                   ({state.orderHistory?.curency})

+ 16 - 22
EsimLao/esim-vite/src/pages/order-history/OrderHistoryView.tsx

@@ -5,7 +5,12 @@ import { useAppDispatch } from "../../hooks/useRedux";
 import { OrderHistory } from "../../services/product/type";
 import { useMutation } from "@tanstack/react-query";
 import React, { useState, useEffect } from "react";
-import { formatCurrency, formatNumber } from "../../logic/loigicUtils";
+import {
+  convertOrderStatusToColor,
+  convertOrderStatusToText,
+  formatCurrency,
+  formatNumber,
+} from "../../logic/loigicUtils";
 import { useTranslation } from "react-i18next";
 
 const OrderHistoryView = () => {
@@ -56,17 +61,6 @@ const OrderHistoryView = () => {
   const inputClass =
     "w-full bg-slate-50 border-2 border-transparent focus:border-[#EE0434]/20 rounded-2xl py-3 px-5 focus:outline-none focus:bg-white transition-all text-slate-700 font-bold placeholder:text-slate-300 text-sm md:text-base h-[50px]";
 
-  const getStatusColor = (status: number) => {
-    switch (status) {
-      case 2:
-        return "bg-[#00c087] text-white";
-      case 1:
-        return "bg-orange-400 text-white";
-      default:
-        return "bg-slate-800 text-white";
-    }
-  };
-
   // const filteredOrders = orders.filter((order) => {
   //   const matchesSearch = order.id.includes(searchOrder);
   //   const matchesStatus = status === "-1" || order.status === status;
@@ -173,9 +167,13 @@ const OrderHistoryView = () => {
                 getOrderMutation.mutate();
               }}
             >
-              <option value="-1">Status</option>
-              <option value="2">Success</option>
-              <option value="1">Pending payment</option>
+              {/* 1: chờ thanh toán 2: đã thanh toán, chờ xuất esim 3: thanh toán
+              thất bại 4: đã trả esim */}
+              <option value="-1">Trạng thái</option>
+              <option value="1">Chờ thanh toán</option>
+              <option value="2">Đã thanh toán, chờ xuất eSIM</option>
+              <option value="3">Thanh toán thất bại</option>
+              <option value="4">Đã trả eSIM</option>
             </select>
             <svg
               className="absolute right-4 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400 pointer-events-none"
@@ -214,15 +212,11 @@ const OrderHistoryView = () => {
               >
                 <div className="space-y-3">
                   <span
-                    className={`inline-block px-3 py-1 rounded-lg text-xs font-black uppercase tracking-wider ${getStatusColor(
-                      order.status
+                    className={`inline-block px-3 py-1 rounded-lg text-xs font-black uppercase tracking-wider ${convertOrderStatusToColor(
+                      order.status,
                     )}`}
                   >
-                    {order.status === 2
-                      ? "Success"
-                      : order.status === 1
-                      ? "Pending payment"
-                      : "Failed"}
+                    {convertOrderStatusToText(order.status)}
                   </span>
                   <div>
                     <p className="text-xl font-black text-slate-900 tracking-tight">

+ 29 - 25
EsimLao/esim-vite/src/pages/product-detail/ProductDetailView.tsx

@@ -25,7 +25,7 @@ const ProductDetailView: React.FC = () => {
   const dispatch = useAppDispatch();
   const { t } = useTranslation();
   // let area = location.state as Area;
-  const areas = getWithExpiry<Area[] | []>("areas");
+  const areas = getWithExpiry<Area[]>("areas");
   const { id } = useParams<{ id: string }>();
   const loading = useAppSelector((state) => state.loading);
   const [selectedDays, setSelectedDays] = useState<number>(null);
@@ -111,6 +111,10 @@ const ProductDetailView: React.FC = () => {
     },
   });
 
+  const convertPackageToSelectedProduct = (packg: Package) => {
+    return packg.title;
+  };
+
   const options = useMemo(() => {
     console.log("Calculating options from loadPackage");
 
@@ -119,20 +123,20 @@ const ProductDetailView: React.FC = () => {
 
     packages.forEach((p) => {
       daysSet.add(p.dayDuration);
-      dataSet.add(p.amountData.toString());
+      dataSet.add(convertPackageToSelectedProduct(p));
     });
 
     const daysArray = Array.from(daysSet).sort((a, b) => a - b);
 
-    const dataArray = Array.from(dataSet).sort((a, b) => {
-      if (a === "Unlimited") return 1;
-      if (b === "Unlimited") return -1;
-      return parseInt(a) - parseInt(b);
-    });
+    // const dataArray = Array.from(dataSet).sort((a, b) => {
+    //   if (a === "Unlimited") return 1;
+    //   if (b === "Unlimited") return -1;
+    //   return parseInt(a) - parseInt(b);
+    // });
 
     return {
       daysArray,
-      dataArray,
+      dataArray: Array.from(dataSet),
     };
   }, [packages]);
 
@@ -154,20 +158,20 @@ const ProductDetailView: React.FC = () => {
     const dataSet = new Set<string>();
     packages.forEach((p) => {
       if (p.dayDuration === day) {
-        dataSet.add(p.amountData.toString());
+        dataSet.add(convertPackageToSelectedProduct(p));
       }
     });
     setSelectedDays(day);
     setSelectedData(
-      dataSet.has(selectedData) ? selectedData : Array.from(dataSet)[0]
+      dataSet.has(selectedData) ? selectedData : Array.from(dataSet)[0],
     );
     setDataActiveOptions(Array.from(dataSet));
     setSelectedPackage(
       packages.find(
         (p) =>
           p.dayDuration === selectedDays &&
-          p.amountData.toString() === selectedData
-      )
+          convertPackageToSelectedProduct(p) === selectedData,
+      ),
     );
   };
 
@@ -175,21 +179,21 @@ const ProductDetailView: React.FC = () => {
     // filter day options based on selected data if needed
     const daysSet = new Set<number>();
     packages.forEach((p) => {
-      if (p.amountData.toString() === data) {
+      if (convertPackageToSelectedProduct(p) === data) {
         daysSet.add(p.dayDuration);
       }
     });
     setSelectedData(data);
     setSelectedDays(
-      daysSet.has(selectedDays) ? selectedDays : Array.from(daysSet)[0]
+      daysSet.has(selectedDays) ? selectedDays : Array.from(daysSet)[0],
     );
     setDaysActiveOptions(Array.from(daysSet));
     setSelectedPackage(
       packages.find(
         (p) =>
           p.dayDuration === selectedDays &&
-          p.amountData.toString() === selectedData
-      )
+          convertPackageToSelectedProduct(p) === selectedData,
+      ),
     );
   };
 
@@ -200,7 +204,7 @@ const ProductDetailView: React.FC = () => {
     let selectedPackageTmp = packages.find(
       (p) =>
         p.dayDuration === selectedDays &&
-        p.amountData.toString() === selectedData
+        convertPackageToSelectedProduct(p) === selectedData,
     );
     if (!selectedPackageTmp) {
       // console.log(
@@ -218,7 +222,7 @@ const ProductDetailView: React.FC = () => {
     }
     console.log(
       "Selected package: ",
-      selectedPackageTmp + " quantity " + quantityToUse
+      selectedPackageTmp + " quantity " + quantityToUse,
     );
     setPrices({
       original: quantityToUse * selectedPackageTmp.displayPrice,
@@ -241,7 +245,7 @@ const ProductDetailView: React.FC = () => {
     const selectedPackage = packages.find(
       (p) =>
         p.dayDuration === selectedDays &&
-        p.amountData.toString() === selectedData
+        convertPackageToSelectedProduct(p) === selectedData,
     );
     if (!selectedPackage) {
       alert("Please select a valid package");
@@ -272,7 +276,7 @@ const ProductDetailView: React.FC = () => {
           title: "Checkout Error",
           message: res.message || "Failed to proceed to checkout.",
           buttonText: "Close",
-        })
+        }),
       );
     }
   };
@@ -368,8 +372,8 @@ const ProductDetailView: React.FC = () => {
                     selectedDays === day
                       ? "border-[#EE0434] text-white bg-[#EE0434] shadow-md"
                       : daysActiveOptions.includes(day)
-                      ? "border-[#ffffff] text-black bg-[#ffffff] shadow-md"
-                      : "border-slate-100 text-slate-300"
+                        ? "border-[#ffffff] text-black bg-[#ffffff] shadow-md"
+                        : "border-slate-100 text-slate-300"
                   }`}
                 >
                   {day}
@@ -394,11 +398,11 @@ const ProductDetailView: React.FC = () => {
                     selectedData === data
                       ? "border-[#EE0434] text-white bg-[#EE0434] shadow-md"
                       : dataActiveOptions.includes(data)
-                      ? "border-[#ffffff] text-black bg-[#ffffff] shadow-md"
-                      : "border-slate-100 text-slate-300"
+                        ? "border-[#ffffff] text-black bg-[#ffffff] shadow-md"
+                        : "border-slate-100 text-slate-300"
                   }`}
                 >
-                  {data === "0" ? "Unlimited" : data + " GB"}
+                  {data === "0" ? "Unlimited" : data}
                 </button>
               ))}
             </div>

+ 5 - 7
EsimLao/esim-vite/src/pages/terms/TermsView.tsx

@@ -365,17 +365,15 @@ const TermsView = () => {
                 </h3>
                 <ul className="list-disc pl-5 mt-2 space-y-1">
                   <li>
-                    <strong>Tên doanh nghiệp:</strong> CÔNG TY CỔ PHẦN GIẢI PHÁP
-                    CÔNG NGHỆ WELLZONE
+                    <strong>Tên doanh nghiệp:</strong> CÔNG TY TNHH Phát triển
+                    toàn cầu VIETTECH
                   </li>
                   <li>
-                    <strong>Giấy chứng nhận ĐKKD:</strong> 0109310641 do Phòng
-                    Đăng ký kinh doanh – Sở Kế hoạch và Đầu tư Hà Nội cấp lần
-                    đầu ngày 17/08/2020
+                    <strong>Giấy chứng nhận ĐKKD:</strong> 0901210362
                   </li>
                   <li>
-                    <strong>Trụ sở chính:</strong> Tầng 10, 83B Lý Thường Kiệt,
-                    Phường Cửa Nam, Thành phố Hà Nội
+                    <strong>Trụ sở chính:</strong> Số 218, Đảo Dừa 1, Khu đô thị
+                    Vinhomes Ocean Park 2, Xã Nghĩa Trụ, Tỉnh Hưng Yên, Việt Nam
                   </li>
                 </ul>