From a2a443924cb8347e86493f525aea21ac02650601 Mon Sep 17 00:00:00 2001
From: Miqdad <ahmadmiqdad27@gmail.com>
Date: Sun, 7 Sep 2025 10:48:03 +0700
Subject: <Miqdad> Initial Commit

---
 src/lib/checkout/components/SectionExpedition.jsx | 152 +++++++++++++---------
 1 file changed, 87 insertions(+), 65 deletions(-)

(limited to 'src/lib/checkout/components/SectionExpedition.jsx')

diff --git a/src/lib/checkout/components/SectionExpedition.jsx b/src/lib/checkout/components/SectionExpedition.jsx
index 2e92ffbc..66182589 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -18,7 +18,7 @@ import { getProductsSla } from '../api/checkoutApi';
 function mappingItems(products) {
   return products?.map((item) => ({
     // name: item.parent.name || item?.name || 'Unknown Product',
-    name:  item?.name,
+    name: item?.name,
     description: `${item.code} - ${item.name}`,
     value: item.price.priceDiscount,
     weight: item.weight * 1000,
@@ -27,61 +27,71 @@ function mappingItems(products) {
 }
 
 function reverseMappingCourier(couriersOdoo, couriers, includeInstant = false) {
-  // Buat peta courier berdasarkan nama courier dari couriers
+  // Bangun peta dari hasil Biteship (pakai dua key: code & name)
   const courierMap = couriers.reduce((acc, item) => {
-    const { courier_name, courier_code, courier_service_code } = item;
-    const key = courier_code.toLowerCase();
-
-    if (
-      !includeInstant && (['hours'].includes(item.shipment_duration_unit.toLowerCase()) || item.service_type == 'same_day')
-      
-    ) {
-      return acc;
-    }
+    const codeKey = (item.courier_code || '').toLowerCase();
+    const nameKey = (item.courier_name || '').toLowerCase();
+
+    const isInstant =
+      (item.shipment_duration_unit || '').toLowerCase() === 'hours' ||
+      (item.service_type || '').toLowerCase() === 'same_day';
+    if (!includeInstant && isInstant) return acc;
+
+    const ensureEntry = (key) => {
+      if (!key) return;
+      if (!acc[key]) {
+        acc[key] = {
+          courier_name: item.courier_name,
+          courier_code: item.courier_code,
+          service_type: {},
+        };
+      }
+    };
 
-    if (!acc[key]) {
-      acc[key] = {
-        courier_name: item.courier_name,
-        courier_code: courier_code,
-        service_type: {},
-      };
-    }
+    ensureEntry(codeKey);
+    ensureEntry(nameKey);
 
-    acc[key].service_type[courier_service_code] = {
+    const svc = {
       service_name: item.courier_service_name,
       duration: item.duration,
       shipment_range: item.shipment_duration_range,
       shipment_unit: item.shipment_duration_unit,
       price: item.price,
-      service_type: courier_service_code,
+      service_type: item.courier_service_code,
       description: item.description,
     };
 
+    if (codeKey && acc[codeKey]) {
+      acc[codeKey].service_type[item.courier_service_code] = svc;
+    }
+    if (nameKey && acc[nameKey]) {
+      acc[nameKey].service_type[item.courier_service_code] = svc;
+    }
     return acc;
   }, {});
 
-  // Iterasi berdasarkan couriersOdoo
-  return couriersOdoo.map((courierOdoo) => {
-    const courierNameKey = courierOdoo.label.toLowerCase();
-    const carrierId = courierOdoo.carrierId;
+  // Petakan Odoo ke map Biteship dan FILTER hanya yg punya layanan
+  return couriersOdoo
+    .map((courierOdoo) => {
+      const key = (courierOdoo.label || '').toLowerCase();
+      const matched = courierMap[key] || null;
 
-    const mappedCourier = courierMap[courierNameKey] || false;
+      if (!matched) return { ...courierOdoo, courier: false };
 
-    if (!mappedCourier) {
       return {
         ...courierOdoo,
-        courier: false,
+        courier: {
+          ...matched,
+          courier_id_odoo: courierOdoo.carrierId, // penting: simpan id Odoo di sini
+        },
       };
-    }
-
-    return {
-      ...courierOdoo,
-      courier: {
-        ...mappedCourier,
-        courier_id_odoo: carrierId,
-      },
-    };
-  });
+    })
+    .filter(
+      (x) =>
+        x.courier &&
+        x.courier.service_type &&
+        Object.keys(x.courier.service_type).length > 0
+    );
 }
 
 function mappingCourier(couriersOdoo, couriers, notIncludeInstant = false) {
@@ -214,7 +224,7 @@ export default function SectionExpedition({ products }) {
 
       let data = {
         products: JSON.stringify(productsMapped),
-      }
+      };
       const res = await odooApi('POST', `/api/v1/product/variants/sla`, data);
       setSlaProducts(res);
     } catch (error) {
@@ -328,13 +338,13 @@ export default function SectionExpedition({ products }) {
   };
 
   useEffect(() => {
-  if (serviceOptions.length > 0) {
-    setSavedServiceOptions(serviceOptions);
-  }
-}, [serviceOptions]);
+    if (serviceOptions.length > 0) {
+      setSavedServiceOptions(serviceOptions);
+    }
+  }, [serviceOptions]);
 
   return (
-    <form >
+    <form>
       <div className='px-4 py-2'>
         <div className='flex justify-between items-center'>
           <div className='font-medium'>Pilih Ekspedisi: </div>
@@ -371,27 +381,40 @@ export default function SectionExpedition({ products }) {
                                 <p className='font-semibold'>SELF PICKUP</p>
                               </div>
                             </div>
-                            {couriers?.map((courier) => (
-                              <div
-                                key={courier?.courier?.courier_code}
-                                onClick={() => onCourierChange(courier)}
-                                className='flex justify-between p-2 items-center hover:bg-gray-100 cursor-pointer'
-                              >
-                                <div>
-                                  <p className='font-semibold'>
-                                    {courier?.label}
-                                  </p>
+                            {couriers
+                              ?.map((c) => c) // sudah ter-filter di reverseMappingCourier, tapi aman buat double-check
+                              .filter(
+                                (c) =>
+                                  c.courier &&
+                                  Object.keys(c.courier.service_type).length > 0
+                              )
+                              .map((courier) => (
+                                <div
+                                  key={
+                                    courier?.courier?.courier_code ||
+                                    courier?.label
+                                  }
+                                  onClick={() => onCourierChange(courier)}
+                                  className='flex justify-between p-2 items-center hover:bg-gray-100 cursor-pointer'
+                                >
+                                  <div>
+                                    <p className='font-semibold'>
+                                      {courier?.label}
+                                    </p>
+                                  </div>
+                                  <span className='font-semibold'>
+                                    <Image
+                                      src={courier?.logo}
+                                      alt={
+                                        courier?.courier?.courier_name ||
+                                        courier?.label
+                                      }
+                                      width={50}
+                                      height={50}
+                                    />
+                                  </span>
                                 </div>
-                                <span className='font-semibold'>
-                                  <Image
-                                    src={courier?.logo}
-                                    alt={courier?.courier?.courier_name}
-                                    width={50}
-                                    height={50}
-                                  />
-                                </span>
-                              </div>
-                            ))}
+                              ))}
                           </>
                         ) : (
                           <>
@@ -432,8 +455,7 @@ export default function SectionExpedition({ products }) {
         )}
       </div>
 
-      {(serviceOptions.length > 0 ||
-        selectedService )&&
+      {(serviceOptions.length > 0 || selectedService) &&
         selectedCourier &&
         selectedCourier !== 32 &&
         selectedCourier !== 0 && (
-- 
cgit v1.2.3

