Explorar o código

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 hai 3 semanas
pai
achega
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