Răsfoiți Sursa

Refactor package loading to use mutation and add util

Replaced the useQuery hook for loading packages with useMutation in ProductDetailView.tsx to better control loading state and error handling. Introduced a new formatNumber utility in loigicUtils.ts for number formatting. Updated all references from loadPackage to packages and adjusted related logic accordingly.
hieubt 3 săptămâni în urmă
părinte
comite
b229a1565b

+ 3 - 0
EsimLao/esim-vite/src/logic/loigicUtils.ts

@@ -0,0 +1,3 @@
+export const formatNumber = (val: number) => {
+    return new Intl.NumberFormat('vi-VN').format(val);
+}

+ 51 - 24
EsimLao/esim-vite/src/pages/product-detail/ProductDetailView.tsx

@@ -2,7 +2,7 @@ import React, { useState, useMemo, useEffect } from "react";
 import { useLocation, useNavigate, Link } from "react-router-dom";
 import { SelectedProduct } from "../../services/types";
 import { Area, Package } from "../../services/product/type";
-import { useQuery } from "@tanstack/react-query";
+import { useMutation, useQuery } from "@tanstack/react-query";
 import { DataCacheKey, staleTime } from "../../global/constants";
 import { useAppDispatch, useAppSelector } from "../../hooks/useRedux";
 import { startLoading, stopLoading } from "../../features/loading/loadingSlice";
@@ -33,6 +33,7 @@ const ProductDetailView: React.FC = () => {
   });
   const [simType, setSimType] = useState<"eSIM" | "Physical">("eSIM");
   const [quantity, setQuantity] = useState<number>(1);
+  const [packages, setPackages] = useState<Package[]>(null);
 
   if (!area) {
     return (
@@ -47,25 +48,51 @@ const ProductDetailView: React.FC = () => {
     );
   }
 
-  const { data: loadPackage = [] } = useQuery<Package[]>({
-    queryKey: [DataCacheKey.PACKAGES],
-    queryFn: async (): Promise<Package[]> => {
-      try {
-        dispatch(startLoading({}));
-        const res = await productApi.loadPackage({
-          areaId: area.id,
-          isUnlimited: "-1",
-          isDaily: "-1",
-        });
-        return res.data as Package[];
-      } catch (error) {
-        console.error(error);
-        return []; // 🔴 bắt buộc
-      } finally {
-        dispatch(stopLoading());
+  // const { data: loadPackage = [] } = useQuery<Package[]>({
+  //   queryKey: [DataCacheKey.PACKAGES],
+  //   queryFn: async (): Promise<Package[]> => {
+  //     try {
+  //       dispatch(startLoading({}));
+  //       const res = await productApi.loadPackage({
+  //         areaId: area.id,
+  //         isUnlimited: "-1",
+  //         isDaily: "-1",
+  //       });
+  //       return res.data as Package[];
+  //     } catch (error) {
+  //       console.error(error);
+  //       return []; // 🔴 bắt buộc
+  //     } finally {
+  //       dispatch(stopLoading());
+  //     }
+  //   },
+  //   staleTime: staleTime,
+  // });
+
+  const getAreaMutation = useMutation({
+    mutationFn: async () => {
+      dispatch(startLoading({}));
+      const res = await productApi.loadPackage({
+        areaId: area.id,
+        isUnlimited: "-1",
+        isDaily: "-1",
+      });
+      return res;
+    },
+    onSuccess: (data) => {
+      dispatch(stopLoading());
+      console.log("Get package response data:", data);
+      if (data && data.errorCode === "0") {
+        console.log("Get package successful");
+        setPackages(data.data as Package[]);
+      } else {
+        console.error("Get package failed, no token received");
       }
     },
-    staleTime: staleTime,
+    onError: (error: any) => {
+      dispatch(stopLoading());
+      console.error("Get package error:", error.response.data);
+    },
   });
 
   const options = useMemo(() => {
@@ -74,7 +101,7 @@ const ProductDetailView: React.FC = () => {
     const daysSet = new Set<number>();
     const dataSet = new Set<string>();
 
-    loadPackage.forEach((p) => {
+    packages.forEach((p) => {
       daysSet.add(p.dayDuration);
       dataSet.add(p.amountData.toString());
     });
@@ -91,7 +118,7 @@ const ProductDetailView: React.FC = () => {
       daysArray,
       dataArray,
     };
-  }, [loadPackage]);
+  }, [packages]);
 
   useEffect(() => {
     setDaysOptions(options.daysArray);
@@ -107,7 +134,7 @@ const ProductDetailView: React.FC = () => {
   const handleSelectDay = (day: number) => {
     // filter data options based on selected day if needed
     const dataSet = new Set<string>();
-    loadPackage.forEach((p) => {
+    packages.forEach((p) => {
       if (p.dayDuration === day) {
         dataSet.add(p.amountData.toString());
       }
@@ -119,7 +146,7 @@ const ProductDetailView: React.FC = () => {
   const handleSelectData = (data: string) => {
     // filter day options based on selected data if needed
     const daysSet = new Set<number>();
-    loadPackage.forEach((p) => {
+    packages.forEach((p) => {
       if (p.amountData.toString() === data) {
         daysSet.add(p.dayDuration);
       }
@@ -132,7 +159,7 @@ const ProductDetailView: React.FC = () => {
     const quantityToUse =
       quantityParam !== undefined ? quantityParam : quantity;
     // find package based on selectedDays and selectedData
-    const selectedPackage = loadPackage.find(
+    const selectedPackage = packages.find(
       (p) =>
         p.dayDuration === selectedDays &&
         p.amountData.toString() === selectedData
@@ -176,7 +203,7 @@ const ProductDetailView: React.FC = () => {
   const handleBuyNow = async () => {
     // Logic for custom order or standard buy
     console.log("Buy now clicked");
-    const selectedPackage = loadPackage.find(
+    const selectedPackage = packages.find(
       (p) =>
         p.dayDuration === selectedDays &&
         p.amountData.toString() === selectedData