From b18d45c560d57c788d3646cf6be0beb6381ec0f7 Mon Sep 17 00:00:00 2001
From: trisusilo48 <tri.susilo@altama.co.id>
Date: Thu, 14 Nov 2024 10:53:54 +0700
Subject: biteship

---
 src/lib/checkout/components/SectionExpedition.jsx | 304 ++++++++++++++++++++++
 1 file changed, 304 insertions(+)
 create mode 100644 src/lib/checkout/components/SectionExpedition.jsx

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

diff --git a/src/lib/checkout/components/SectionExpedition.jsx b/src/lib/checkout/components/SectionExpedition.jsx
new file mode 100644
index 00000000..ead65a6f
--- /dev/null
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -0,0 +1,304 @@
+import React, { useEffect, useState } from 'react';
+import { useQuery } from 'react-query';
+import GetRatesCourierBiteship from '../api/getRatesCourier';
+import { useAddress } from '../stores/useAdress';
+import axios, { AxiosResponse } from 'axios';
+import { useForm, Controller } from 'react-hook-form';
+import { AnimatePresence, motion } from 'framer-motion';
+import { Spinner } from '@chakra-ui/react';
+
+import currencyFormat from '@/core/utils/currencyFormat';
+
+function mappingItems(products) {
+  return products?.map((item) => ({
+    name: item.parent.name,
+    description: `${item.code} - ${item.name}`,
+    value: item.price.priceDiscount,
+    weight: item.weight,
+    quantity: item.quantity,
+  }));
+}
+
+function mappingCourier(couriers) {
+  return couriers?.reduce((result, item) => {
+    const { courier_code, courier_service_code } = item;
+
+    // Jika courier_code belum ada di result, buat objek baru untuknya
+    if (!result[courier_code]) {
+      result[courier_code] = {
+        courier_name: item.courier_name,
+        courier_code: courier_code,
+        service_type: {
+          [courier_service_code]: {
+            service_name: item.courier_service_name,
+            duration: item.duration,
+            shipment_duration: item.duration,
+            price: item.price,
+            service_type: item.service_type,
+            description: item.description,
+          },
+        },
+      };
+    } else {
+      result[courier_code].service_type[courier_service_code] = {
+        service_name: item.courier_service_name,
+        duration: item.duration,
+        shipment_duration: item.duration,
+        price: item.price,
+        service_type: item.service_type,
+        description: item.description,
+      };
+    }
+
+    return result;
+  }, {});
+}
+
+// interface CourierService {
+//   courier_name: string;
+//   courier_code: string;
+//   service_type: {
+//     [key: string]: {
+//       service_name: string;
+//       duration: number;
+//       shipment_duration: number;
+//       price: number;
+//       service_type: string;
+//       description: string;
+//     };
+//   };
+// }
+
+// interface ServiceOption {
+//   service_name: string;
+//   duration: number;
+//   shipment_duration: number;
+//   price: number;
+//   service_type: string;
+//   description: string;
+// }
+
+export default function SectionExpedition({ products }) {
+  const { addressMaps, coordinate, postalCode } = useAddress();
+  const { control, handleSubmit } = useForm();
+  const [selectedCourier, setSelectedCourier] = useState('');
+  const [serviceOptions, setServiceOptions] = useState([]);
+  const [selectedService, setSelectedService] = useState(null);
+  const [isOpen, setIsOpen] = useState(false);
+
+  let destination = {};
+  let items = mappingItems(products);
+  if (addressMaps) {
+    destination = {
+      origin_latitude: -6.3031123,
+      origin_longitude: 106.7794934999,
+      ...coordinate,
+    };
+  } else if (postalCode) {
+    destination = {
+      origin_postal_code: 12440,
+      destination_postal_code: postalCode,
+    };
+  }
+
+  const fetchExpedition = async () => {
+    let body = {
+      ...destination,
+      couriers:
+        'gojek,grab,deliveree,lalamove,jne,tiki,ninja,lion,rara,sicepat,jnt,pos,idexpress,rpx,wahana,jdl,pos,anteraja,sap,paxel,borzo',
+      items: items,
+    };
+    try {
+      const response = await axios.get(`/api/biteship-service`, {
+        params: { body: JSON.stringify(body) },
+      });
+      return response;
+    } catch (error) {
+      console.error('Failed to fetch expedition rates:', error);
+    }
+  };
+
+  // const fetchExpedition = async () => await GetRatesCourierBiteship({ destination, items });
+  const { data, isLoading } = useQuery(
+    ['expedition', JSON.stringify(destination), JSON.stringify(items)],
+    fetchExpedition,
+    {
+      enabled: Boolean(Object.keys(destination).length) && items?.length > 0,
+      staleTime: Infinity,
+      cacheTime: Infinity,
+    }
+  );
+
+  const couriers = mappingCourier(data?.data?.pricing);
+
+  console.log('couriers', couriers);
+
+  const onCourierChange = (e) => {
+    const courier = e.target.value;
+    console.log('courier', courier);
+    setSelectedCourier(courier);
+    // Menentukan layanan berdasarkan pengiriman yang dipilih
+    if (courier && couriers[courier]) {
+      setServiceOptions(Object.values(couriers[courier]?.service_type));
+    } else {
+      setServiceOptions([]);
+    }
+  };
+
+  const onSubmit = (data) => {
+    console.log(data);
+  };
+
+  const handleSelect = (service) => {
+    setSelectedService(service);
+    setIsOpen(false);
+  };
+
+  return (
+    <form onSubmit={handleSubmit(onSubmit)}>
+      {/* Dropdown untuk memilih jenis pengiriman */}
+      <div className='px-4 py-2'>
+        <div className='flex justify-between items-center'>
+          <div className='font-medium'>Pilih Ekspedisi: </div>
+          <div className='w-[250px]'>
+            <div className='flex items-center gap-x-4'>
+              <select
+                className={`form-input `}
+                onChange={onCourierChange}
+                required
+              >
+                <option value='0,0'>Pilih Pengiriman</option>
+                <option value='1,32'>SELF PICKUP</option>
+                {couriers &&
+                  Object.values(couriers)?.map((expedisi) => (
+                    <option
+                      value={expedisi.courier_code}
+                      key={expedisi.courier_name}
+                    >
+                      {' '}
+                      {expedisi.courier_name}
+                    </option>
+                  ))}
+              </select>
+
+              <AnimatePresence>
+                {isLoading && (
+                  <motion.div
+                    initial={{ opacity: 0, width: 0 }}
+                    animate={{ opacity: 1, width: '28px' }}
+                    exit={{ opacity: 0, width: 0 }}
+                    transition={{
+                      duration: 0.25,
+                    }}
+                    className='overflow-hidden'
+                  >
+                    <Spinner thickness='3px' speed='0.5s' color='red.500' />
+                  </motion.div>
+                )}
+              </AnimatePresence>
+            </div>
+            {/* {checkoutValidation && (
+            <span className='text-sm text-red-500'>
+              *silahkan pilih expedisi
+            </span>
+          )} */}
+          </div>
+          {/* <style jsx>{`
+          .shake {
+            animation: shake 0.4s ease-in-out;
+          }
+        `}</style> */}
+        </div>
+        {/* {checkWeigth == true && (
+        <p className='mt-4 text-gray_r-11 leading-6'>
+          Mohon maaf, pengiriman hanya tersedia untuk self pickup karena
+          terdapat barang yang belum diatur beratnya. Mohon atur berat barang
+          dengan menghubungi admin melalui{' '}
+          <a
+            className='text-danger-500 inline'
+            href='https://api.whatsapp.com/send?phone=6281717181922'
+          >
+            tautan ini
+          </a>
+        </p>
+      )} */}
+      </div>
+
+      {selectedCourier && (
+        <div className='px-4 py-2'>
+          <div className='flex justify-between items-center'>
+            <div className='font-medium'>Tipe Layanan Ekspedisi: </div>
+            <div className='w-[350px]'>
+              <div className='relative'>
+                {/* Custom Select Input Field */}
+                <div
+                  className='w-full p-2 border rounded-lg bg-white cursor-pointer'
+                  onClick={() => setIsOpen(!isOpen)}
+                >
+                  {selectedService ? (
+                    <div className='flex justify-between'>
+                      <span>{selectedService.service_name}</span>
+                      <span className='font-semibold'>
+                        {currencyFormat(selectedService.price)}
+                      </span>
+                    </div>
+                  ) : (
+                    <span className='text-gray-500'>
+                      Pilih layanan pengiriman
+                    </span>
+                  )}
+                </div>
+
+                {/* Dropdown Options */}
+                {isOpen && (
+                  <div className='absolute w-full bg-white border rounded-lg mt-1 shadow-lg z-10'>
+                    {serviceOptions.map((service) => (
+                      <div
+                        key={service.service_type}
+                        onClick={() => handleSelect(service)}
+                        className='flex justify-between p-2 items-center hover:bg-gray-100 cursor-pointer'
+                      >
+                        <div>
+                          <p className='font-semibold'>
+                            {service.service_name}
+                          </p>
+                          <p className='text-gray-600 text-sm'>
+                            Estimasi Tiba {service.duration}
+                          </p>
+                        </div>
+                        <span className='font-semibold'>{currencyFormat(service.price)}</span>
+                      </div>
+                    ))}
+                  </div>
+                )}
+              </div>
+              {/* <select
+                className='form-input'
+                // onChange={(e) => setSelectedServiceType(e.target.value)}
+              >
+                {serviceOptions.map(
+                  (service: { service_name: string; service_type: string; duration: string, price: number }) => (
+                    <option
+                      value={service?.service_type}
+                      key={service.service_type}
+                    >
+                      <div className='flex items-center gap-x-4'>
+                        <div>
+                          <label>{service?.service_name}</label>
+                          <span> Estimasi Tiba {service?.duration} </span>
+                        </div>
+                        <div>
+                          <label>{service.price}</label>
+                        </div>
+                      </div>
+                    </option>
+                  )
+                )}
+              </select> */}
+            </div>
+          </div>
+        </div>
+      )}
+    </form>
+  );
+}
-- 
cgit v1.2.3


From d078c6adfd896b59f14e2a5116ecb977256674fa Mon Sep 17 00:00:00 2001
From: trisusilo48 <tri.susilo@altama.co.id>
Date: Tue, 19 Nov 2024 16:51:54 +0700
Subject: biteships

---
 src/lib/checkout/components/SectionExpedition.jsx | 216 +++++++++++-----------
 1 file changed, 108 insertions(+), 108 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 ead65a6f..27224e5b 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -1,27 +1,34 @@
-import React, { useEffect, useState } from 'react';
+import { Spinner } from '@chakra-ui/react';
+import axios from 'axios';
+import { AnimatePresence, motion } from 'framer-motion';
+import React, { useState } from 'react';
+import { useForm } from 'react-hook-form';
 import { useQuery } from 'react-query';
-import GetRatesCourierBiteship from '../api/getRatesCourier';
 import { useAddress } from '../stores/useAdress';
-import axios, { AxiosResponse } from 'axios';
-import { useForm, Controller } from 'react-hook-form';
-import { AnimatePresence, motion } from 'framer-motion';
-import { Spinner } from '@chakra-ui/react';
 
 import currencyFormat from '@/core/utils/currencyFormat';
+import { useCheckout } from '../stores/stateCheckout';
 
 function mappingItems(products) {
   return products?.map((item) => ({
     name: item.parent.name,
     description: `${item.code} - ${item.name}`,
     value: item.price.priceDiscount,
-    weight: item.weight,
+    weight: item.weight * 1000 * item.quantity,
     quantity: item.quantity,
+    canInstant: item.availableQuantity > item.quantity ? true : false,
   }));
 }
 
-function mappingCourier(couriers) {
+function mappingCourier(couriers, notIncludeInstant = false) {
   return couriers?.reduce((result, item) => {
     const { courier_code, courier_service_code } = item;
+    if (
+      notIncludeInstant &&
+      ['hours'].includes(item.shipment_duration_unit.toLowerCase())
+    ) {
+      return result;
+    }
 
     // Jika courier_code belum ada di result, buat objek baru untuknya
     if (!result[courier_code]) {
@@ -54,6 +61,10 @@ function mappingCourier(couriers) {
   }, {});
 }
 
+function hasCanInstantFalse(items) {
+  return items.some((item) => item.canInstant === false);
+}
+
 // interface CourierService {
 //   courier_name: string;
 //   courier_code: string;
@@ -86,8 +97,13 @@ export default function SectionExpedition({ products }) {
   const [selectedService, setSelectedService] = useState(null);
   const [isOpen, setIsOpen] = useState(false);
 
+  const { checkWeigth, checkoutValidation } = useCheckout();
+
   let destination = {};
   let items = mappingItems(products);
+
+  let notIncludeInstant = hasCanInstantFalse(items);
+  console.log('instanCourier', items);
   if (addressMaps) {
     destination = {
       origin_latitude: -6.3031123,
@@ -118,27 +134,31 @@ export default function SectionExpedition({ products }) {
     }
   };
 
-  // const fetchExpedition = async () => await GetRatesCourierBiteship({ destination, items });
   const { data, isLoading } = useQuery(
     ['expedition', JSON.stringify(destination), JSON.stringify(items)],
     fetchExpedition,
     {
-      enabled: Boolean(Object.keys(destination).length) && items?.length > 0,
+      enabled:
+        Boolean(Object.keys(destination).length) &&
+        items?.length > 0 &&
+        !checkWeigth,
       staleTime: Infinity,
       cacheTime: Infinity,
     }
   );
 
-  const couriers = mappingCourier(data?.data?.pricing);
+  console.log('data', data);
 
-  console.log('couriers', couriers);
+  const couriers = mappingCourier(data?.data?.pricing, true) || null;
 
   const onCourierChange = (e) => {
+    setIsOpen(false);
     const courier = e.target.value;
-    console.log('courier', courier);
+    setSelectedService(null);
     setSelectedCourier(courier);
+    console.log('courier', courier);
     // Menentukan layanan berdasarkan pengiriman yang dipilih
-    if (courier && couriers[courier]) {
+    if (courier && courier !== '0' && courier !== '32' && couriers[courier]) {
       setServiceOptions(Object.values(couriers[courier]?.service_type));
     } else {
       setServiceOptions([]);
@@ -156,7 +176,6 @@ export default function SectionExpedition({ products }) {
 
   return (
     <form onSubmit={handleSubmit(onSubmit)}>
-      {/* Dropdown untuk memilih jenis pengiriman */}
       <div className='px-4 py-2'>
         <div className='flex justify-between items-center'>
           <div className='font-medium'>Pilih Ekspedisi: </div>
@@ -167,8 +186,8 @@ export default function SectionExpedition({ products }) {
                 onChange={onCourierChange}
                 required
               >
-                <option value='0,0'>Pilih Pengiriman</option>
-                <option value='1,32'>SELF PICKUP</option>
+                <option value='0'>Pilih Pengiriman</option>
+                <option value='32'>SELF PICKUP</option>
                 {couriers &&
                   Object.values(couriers)?.map((expedisi) => (
                     <option
@@ -197,108 +216,89 @@ export default function SectionExpedition({ products }) {
                 )}
               </AnimatePresence>
             </div>
-            {/* {checkoutValidation && (
-            <span className='text-sm text-red-500'>
-              *silahkan pilih expedisi
-            </span>
-          )} */}
+            {checkoutValidation && (
+              <span className='text-sm text-red-500'>
+                *silahkan pilih expedisi
+              </span>
+            )}
           </div>
-          {/* <style jsx>{`
-          .shake {
-            animation: shake 0.4s ease-in-out;
-          }
-        `}</style> */}
+          <style jsx>{`
+            .shake {
+              animation: shake 0.4s ease-in-out;
+            }
+          `}</style>
         </div>
-        {/* {checkWeigth == true && (
-        <p className='mt-4 text-gray_r-11 leading-6'>
-          Mohon maaf, pengiriman hanya tersedia untuk self pickup karena
-          terdapat barang yang belum diatur beratnya. Mohon atur berat barang
-          dengan menghubungi admin melalui{' '}
-          <a
-            className='text-danger-500 inline'
-            href='https://api.whatsapp.com/send?phone=6281717181922'
-          >
-            tautan ini
-          </a>
-        </p>
-      )} */}
+        {checkWeigth == true && (
+          <p className='mt-4 text-gray_r-11 leading-6'>
+            Mohon maaf, pengiriman hanya tersedia untuk self pickup karena
+            terdapat barang yang belum diatur beratnya. Mohon atur berat barang
+            dengan menghubungi admin melalui{' '}
+            <a
+              className='text-danger-500 inline'
+              href='https://api.whatsapp.com/send?phone=6281717181922'
+            >
+              tautan ini
+            </a>
+          </p>
+        )}
       </div>
 
-      {selectedCourier && (
-        <div className='px-4 py-2'>
-          <div className='flex justify-between items-center'>
-            <div className='font-medium'>Tipe Layanan Ekspedisi: </div>
-            <div className='w-[350px]'>
-              <div className='relative'>
-                {/* Custom Select Input Field */}
-                <div
-                  className='w-full p-2 border rounded-lg bg-white cursor-pointer'
-                  onClick={() => setIsOpen(!isOpen)}
-                >
-                  {selectedService ? (
-                    <div className='flex justify-between'>
-                      <span>{selectedService.service_name}</span>
-                      <span className='font-semibold'>
-                        {currencyFormat(selectedService.price)}
+      {selectedCourier &&
+        selectedCourier !== '32' &&
+        selectedCourier !== '0' && (
+          <div className='px-4 py-2'>
+            <div className='flex justify-between items-center'>
+              <div className='font-medium'>Tipe Layanan Ekspedisi: </div>
+              <div className='w-[350px]'>
+                <div className='relative'>
+                  {/* Custom Select Input Field */}
+                  <div
+                    className='w-full p-2 border rounded-lg bg-white cursor-pointer'
+                    onClick={() => setIsOpen(!isOpen)}
+                  >
+                    {selectedService ? (
+                      <div className='flex justify-between'>
+                        <span>{selectedService.service_name}</span>
+                        <span className='font-semibold'>
+                          {currencyFormat(selectedService.price)}
+                        </span>
+                      </div>
+                    ) : (
+                      <span className='text-gray-500'>
+                        Pilih layanan pengiriman
                       </span>
+                    )}
+                  </div>
+
+                  {/* Dropdown Options */}
+                  {isOpen && (
+                    <div className='absolute w-full bg-white border rounded-lg mt-1 shadow-lg z-10'>
+                      {serviceOptions.map((service) => (
+                        <div
+                          key={service.service_type}
+                          onClick={() => handleSelect(service)}
+                          className='flex justify-between p-2 items-center hover:bg-gray-100 cursor-pointer'
+                        >
+                          <div>
+                            <p className='font-semibold'>
+                              {service.service_name}
+                            </p>
+                            <p className='text-gray-600 text-sm'>
+                              Estimasi Tiba {service.duration}
+                            </p>
+                          </div>
+                          <span className='font-semibold'>
+                            {currencyFormat(service.price)}
+                          </span>
+                        </div>
+                      ))}
                     </div>
-                  ) : (
-                    <span className='text-gray-500'>
-                      Pilih layanan pengiriman
-                    </span>
                   )}
                 </div>
-
-                {/* Dropdown Options */}
-                {isOpen && (
-                  <div className='absolute w-full bg-white border rounded-lg mt-1 shadow-lg z-10'>
-                    {serviceOptions.map((service) => (
-                      <div
-                        key={service.service_type}
-                        onClick={() => handleSelect(service)}
-                        className='flex justify-between p-2 items-center hover:bg-gray-100 cursor-pointer'
-                      >
-                        <div>
-                          <p className='font-semibold'>
-                            {service.service_name}
-                          </p>
-                          <p className='text-gray-600 text-sm'>
-                            Estimasi Tiba {service.duration}
-                          </p>
-                        </div>
-                        <span className='font-semibold'>{currencyFormat(service.price)}</span>
-                      </div>
-                    ))}
-                  </div>
-                )}
               </div>
-              {/* <select
-                className='form-input'
-                // onChange={(e) => setSelectedServiceType(e.target.value)}
-              >
-                {serviceOptions.map(
-                  (service: { service_name: string; service_type: string; duration: string, price: number }) => (
-                    <option
-                      value={service?.service_type}
-                      key={service.service_type}
-                    >
-                      <div className='flex items-center gap-x-4'>
-                        <div>
-                          <label>{service?.service_name}</label>
-                          <span> Estimasi Tiba {service?.duration} </span>
-                        </div>
-                        <div>
-                          <label>{service.price}</label>
-                        </div>
-                      </div>
-                    </option>
-                  )
-                )}
-              </select> */}
             </div>
           </div>
-        </div>
-      )}
+        )}
     </form>
   );
 }
-- 
cgit v1.2.3


From 821d218ff687a585c99937948989408541b596e4 Mon Sep 17 00:00:00 2001
From: trisusilo48 <tri.susilo@altama.co.id>
Date: Tue, 26 Nov 2024 09:46:07 +0700
Subject: filter biteship courier sesuikan dengan courier dari odoo

---
 src/lib/checkout/components/SectionExpedition.jsx | 118 ++++++++++++++--------
 1 file changed, 75 insertions(+), 43 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 27224e5b..be40a577 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -1,4 +1,4 @@
-import { Spinner } from '@chakra-ui/react';
+import { Skeleton, Spinner } from '@chakra-ui/react';
 import axios from 'axios';
 import { AnimatePresence, motion } from 'framer-motion';
 import React, { useState } from 'react';
@@ -14,15 +14,25 @@ function mappingItems(products) {
     name: item.parent.name,
     description: `${item.code} - ${item.name}`,
     value: item.price.priceDiscount,
-    weight: item.weight * 1000 * item.quantity,
+    weight: item.weight * 1000,
     quantity: item.quantity,
     canInstant: item.availableQuantity > item.quantity ? true : false,
   }));
 }
 
-function mappingCourier(couriers, notIncludeInstant = false) {
+function mappingCourier(couriersOdoo, couriers, notIncludeInstant = false) {
+  const validCourierMap = couriersOdoo.reduce((acc, courier) => {
+    acc[courier.label.toLowerCase()] = courier.carrierId;
+    return acc;
+  }, {});
+
   return couriers?.reduce((result, item) => {
-    const { courier_code, courier_service_code } = item;
+    const { courier_name, courier_code, courier_service_code } = item;
+    if (!validCourierMap[courier_name.toLowerCase()]) {
+      return result; // Jika tidak ada, lewati item ini
+    }
+
+
     if (
       notIncludeInstant &&
       ['hours'].includes(item.shipment_duration_unit.toLowerCase())
@@ -30,16 +40,20 @@ function mappingCourier(couriers, notIncludeInstant = false) {
       return result;
     }
 
+    const carrierId = validCourierMap[courier_name];
+
     // Jika courier_code belum ada di result, buat objek baru untuknya
     if (!result[courier_code]) {
       result[courier_code] = {
         courier_name: item.courier_name,
         courier_code: courier_code,
+        courier_id_odoo : carrierId,
         service_type: {
           [courier_service_code]: {
             service_name: item.courier_service_name,
             duration: item.duration,
-            shipment_duration: item.duration,
+            shipment_range: item.shipment_duration_range,
+            shipment_unit: item.shipment_duration_unit,
             price: item.price,
             service_type: item.service_type,
             description: item.description,
@@ -50,6 +64,8 @@ function mappingCourier(couriers, notIncludeInstant = false) {
       result[courier_code].service_type[courier_service_code] = {
         service_name: item.courier_service_name,
         duration: item.duration,
+        shipment_range: item.shipment_duration_range,
+        shipment_unit: item.shipment_duration_unit,
         shipment_duration: item.duration,
         price: item.price,
         service_type: item.service_type,
@@ -92,18 +108,27 @@ function hasCanInstantFalse(items) {
 export default function SectionExpedition({ products }) {
   const { addressMaps, coordinate, postalCode } = useAddress();
   const { control, handleSubmit } = useForm();
-  const [selectedCourier, setSelectedCourier] = useState('');
   const [serviceOptions, setServiceOptions] = useState([]);
-  const [selectedService, setSelectedService] = useState(null);
   const [isOpen, setIsOpen] = useState(false);
+  const [onFocusSelectedCourier, setOnFocuseSelectedCourier] = useState(false);
 
-  const { checkWeigth, checkoutValidation } = useCheckout();
+  const {
+    checkWeigth,
+    checkoutValidation,
+    setBiayaKirim,
+    setUnit,
+    setEtd,
+    selectedCourier,
+    setSelectedCourier,
+    selectedService,
+    setSelectedService,
+    listExpedisi,
+  } = useCheckout();
 
   let destination = {};
   let items = mappingItems(products);
 
   let notIncludeInstant = hasCanInstantFalse(items);
-  console.log('instanCourier', items);
   if (addressMaps) {
     destination = {
       origin_latitude: -6.3031123,
@@ -112,7 +137,7 @@ export default function SectionExpedition({ products }) {
     };
   } else if (postalCode) {
     destination = {
-      origin_postal_code: 12440,
+      origin_postal_code: 14440,
       destination_postal_code: postalCode,
     };
   }
@@ -141,23 +166,26 @@ export default function SectionExpedition({ products }) {
       enabled:
         Boolean(Object.keys(destination).length) &&
         items?.length > 0 &&
-        !checkWeigth,
+        !checkWeigth &&
+        onFocusSelectedCourier,
       staleTime: Infinity,
       cacheTime: Infinity,
     }
   );
 
-  console.log('data', data);
+  const couriers =
+    mappingCourier(listExpedisi, data?.data?.pricing, notIncludeInstant) ||
+    null;
 
-  const couriers = mappingCourier(data?.data?.pricing, true) || null;
+  console.log('ini scourier', data?.data?.pricing)
 
   const onCourierChange = (e) => {
     setIsOpen(false);
     const courier = e.target.value;
     setSelectedService(null);
     setSelectedCourier(courier);
-    console.log('courier', courier);
-    // Menentukan layanan berdasarkan pengiriman yang dipilih
+    // setSelectedCourierId(Object.values(couriers[courier]?.courier_id_odoo);
+    setBiayaKirim(0);
     if (courier && courier !== '0' && courier !== '32' && couriers[courier]) {
       setServiceOptions(Object.values(couriers[courier]?.service_type));
     } else {
@@ -165,12 +193,15 @@ export default function SectionExpedition({ products }) {
     }
   };
 
-  const onSubmit = (data) => {
+  const onSubmit = (data) => {1
     console.log(data);
   };
 
   const handleSelect = (service) => {
     setSelectedService(service);
+    setBiayaKirim(service?.price);
+    setEtd(service?.shipment_range);
+    setUnit(service?.shipment_unit);
     setIsOpen(false);
   };
 
@@ -184,37 +215,38 @@ export default function SectionExpedition({ products }) {
               <select
                 className={`form-input `}
                 onChange={onCourierChange}
+                onMouseDown={() => setOnFocuseSelectedCourier(true)}
                 required
               >
-                <option value='0'>Pilih Pengiriman</option>
-                <option value='32'>SELF PICKUP</option>
-                {couriers &&
-                  Object.values(couriers)?.map((expedisi) => (
-                    <option
-                      value={expedisi.courier_code}
-                      key={expedisi.courier_name}
-                    >
-                      {' '}
-                      {expedisi.courier_name}
+                {!isLoading ? (
+                  <>
+                    <option value='0'>Pilih Pengiriman</option>
+                    <option value='32'>SELF PICKUP</option>
+                    {couriers &&
+                      Object.values(couriers)?.map((expedisi) => (
+                        <option
+                          value={expedisi.courier_code}
+                          key={expedisi.courier_name}
+                        >
+                          {' '}
+                          {expedisi.courier_name}
+                        </option>
+                      ))}
+                  </>
+                ) : (
+                  <>
+                    <option disabled className='skeleton-option'>
+                      <Skeleton height={40} containerClassName='w-full' />
                     </option>
-                  ))}
-              </select>
-
-              <AnimatePresence>
-                {isLoading && (
-                  <motion.div
-                    initial={{ opacity: 0, width: 0 }}
-                    animate={{ opacity: 1, width: '28px' }}
-                    exit={{ opacity: 0, width: 0 }}
-                    transition={{
-                      duration: 0.25,
-                    }}
-                    className='overflow-hidden'
-                  >
-                    <Spinner thickness='3px' speed='0.5s' color='red.500' />
-                  </motion.div>
+                    <option disabled className='skeleton-option'>
+                      <Skeleton height={40} containerClassName='w-full' />
+                    </option>
+                    <option disabled className='skeleton-option'>
+                      <Skeleton height={40} containerClassName='w-full' />
+                    </option>
+                  </>
                 )}
-              </AnimatePresence>
+              </select>
             </div>
             {checkoutValidation && (
               <span className='text-sm text-red-500'>
-- 
cgit v1.2.3


From d1592286eef165533c21d52aec70dbb703cdcfd3 Mon Sep 17 00:00:00 2001
From: trisusilo48 <tri.susilo@altama.co.id>
Date: Wed, 18 Dec 2024 15:03:52 +0700
Subject: feedback uat

---
 src/lib/checkout/components/SectionExpedition.jsx | 24 ++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 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 be40a577..2098d5b5 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -8,6 +8,7 @@ import { useAddress } from '../stores/useAdress';
 
 import currencyFormat from '@/core/utils/currencyFormat';
 import { useCheckout } from '../stores/stateCheckout';
+import { formatShipmentRange } from '../utils/functionCheckouit';
 
 function mappingItems(products) {
   return products?.map((item) => ({
@@ -32,7 +33,6 @@ function mappingCourier(couriersOdoo, couriers, notIncludeInstant = false) {
       return result; // Jika tidak ada, lewati item ini
     }
 
-
     if (
       notIncludeInstant &&
       ['hours'].includes(item.shipment_duration_unit.toLowerCase())
@@ -47,7 +47,7 @@ function mappingCourier(couriersOdoo, couriers, notIncludeInstant = false) {
       result[courier_code] = {
         courier_name: item.courier_name,
         courier_code: courier_code,
-        courier_id_odoo : carrierId,
+        courier_id_odoo: carrierId,
         service_type: {
           [courier_service_code]: {
             service_name: item.courier_service_name,
@@ -177,7 +177,7 @@ export default function SectionExpedition({ products }) {
     mappingCourier(listExpedisi, data?.data?.pricing, notIncludeInstant) ||
     null;
 
-  console.log('ini scourier', data?.data?.pricing)
+  console.log('ini scourier', data?.data?.pricing);
 
   const onCourierChange = (e) => {
     setIsOpen(false);
@@ -193,7 +193,8 @@ export default function SectionExpedition({ products }) {
     }
   };
 
-  const onSubmit = (data) => {1
+  const onSubmit = (data) => {
+    1;
     console.log(data);
   };
 
@@ -292,7 +293,10 @@ export default function SectionExpedition({ products }) {
                       <div className='flex justify-between'>
                         <span>{selectedService.service_name}</span>
                         <span className='font-semibold'>
-                          {currencyFormat(selectedService.price)}
+                          {currencyFormat(
+                            Math.round(parseInt(selectedService?.price * 1.1) / 1000) *
+                              1000
+                          )}
                         </span>
                       </div>
                     ) : (
@@ -316,11 +320,17 @@ export default function SectionExpedition({ products }) {
                               {service.service_name}
                             </p>
                             <p className='text-gray-600 text-sm'>
-                              Estimasi Tiba {service.duration}
+                              {formatShipmentRange(
+                                service.shipment_range,
+                                service.shipment_unit
+                              )}
                             </p>
                           </div>
                           <span className='font-semibold'>
-                            {currencyFormat(service.price)}
+                            {currencyFormat(
+                              Math.round(parseInt(service?.price * 1.1) / 1000) *
+                                1000
+                            )}
                           </span>
                         </div>
                       ))}
-- 
cgit v1.2.3


From 5559770e0b0e94b68de1e31bf2be5c978362821d Mon Sep 17 00:00:00 2001
From: trisusilo48 <tri.susilo@altama.co.id>
Date: Tue, 31 Dec 2024 09:01:10 +0700
Subject: logo and mapping courier

---
 src/lib/checkout/components/SectionExpedition.jsx | 214 ++++++++++++++++------
 1 file changed, 157 insertions(+), 57 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 2098d5b5..8b59d210 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -1,7 +1,7 @@
 import { Skeleton, Spinner } from '@chakra-ui/react';
 import axios from 'axios';
 import { AnimatePresence, motion } from 'framer-motion';
-import React, { useState } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
 import { useForm } from 'react-hook-form';
 import { useQuery } from 'react-query';
 import { useAddress } from '../stores/useAdress';
@@ -9,6 +9,8 @@ import { useAddress } from '../stores/useAdress';
 import currencyFormat from '@/core/utils/currencyFormat';
 import { useCheckout } from '../stores/stateCheckout';
 import { formatShipmentRange } from '../utils/functionCheckouit';
+import Image from 'next/image';
+import toast from 'react-hot-toast';
 
 function mappingItems(products) {
   return products?.map((item) => ({
@@ -21,6 +23,57 @@ function mappingItems(products) {
   }));
 }
 
+function reverseMappingCourier(couriersOdoo, couriers) {
+  // Buat peta courier berdasarkan nama courier dari couriers
+  const courierMap = couriers.reduce((acc, item) => {
+    const { courier_name, courier_code, courier_service_code } = item;
+    const key = courier_name.toLowerCase();
+
+    if (!acc[key]) {
+      acc[key] = {
+        courier_name: item.courier_name,
+        courier_code: courier_code,
+        service_type: {},
+      };
+    }
+
+    acc[key].service_type[courier_service_code] = {
+      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: item.service_type,
+      description: item.description,
+    };
+
+    return acc;
+  }, {});
+
+  // Iterasi berdasarkan couriersOdoo
+  return couriersOdoo.map((courierOdoo) => {
+    const courierNameKey = courierOdoo.label.toLowerCase();
+    const carrierId = courierOdoo.carrierId;
+
+    const mappedCourier = courierMap[courierNameKey] || false;
+
+    if (!mappedCourier) {
+      return {
+        ...courierOdoo,
+        courier: false,
+      };
+    }
+
+    return {
+      ...courierOdoo,
+      courier: {
+        ...mappedCourier,
+        courier_id_odoo: carrierId,
+      },
+    };
+  });
+}
+
 function mappingCourier(couriersOdoo, couriers, notIncludeInstant = false) {
   const validCourierMap = couriersOdoo.reduce((acc, courier) => {
     acc[courier.label.toLowerCase()] = courier.carrierId;
@@ -110,7 +163,9 @@ export default function SectionExpedition({ products }) {
   const { control, handleSubmit } = useForm();
   const [serviceOptions, setServiceOptions] = useState([]);
   const [isOpen, setIsOpen] = useState(false);
+  const [selectedE, setIsOpenCourier] = useState(false);
   const [onFocusSelectedCourier, setOnFocuseSelectedCourier] = useState(false);
+  const [couriers, setCouriers] = useState(null);
 
   const {
     checkWeigth,
@@ -173,22 +228,31 @@ export default function SectionExpedition({ products }) {
     }
   );
 
-  const couriers =
-    mappingCourier(listExpedisi, data?.data?.pricing, notIncludeInstant) ||
-    null;
+  console.log('ini response', data);
 
-  console.log('ini scourier', data?.data?.pricing);
+  useEffect(() => {
+    if (data) {
+      const couriers = reverseMappingCourier(listExpedisi, data?.data?.pricing);
+      setCouriers(couriers);
+      console.log('ini scourier', couriers);
+    }
+  }, [data]);
 
-  const onCourierChange = (e) => {
+  const onCourierChange = (code) => {
     setIsOpen(false);
-    const courier = e.target.value;
+    setOnFocuseSelectedCourier(false);
+    const courier = code;
     setSelectedService(null);
-    setSelectedCourier(courier);
-    // setSelectedCourierId(Object.values(couriers[courier]?.courier_id_odoo);
     setBiayaKirim(0);
-    if (courier && courier !== '0' && courier !== '32' && couriers[courier]) {
-      setServiceOptions(Object.values(couriers[courier]?.service_type));
+    if (courier !== 0 && courier !== 32) {
+      if (courier.courier) {
+        setSelectedCourier(courier.courier.courier_code);
+        setServiceOptions(Object.values(courier.courier.service_type));
+      } else {
+        toast.error('Maaf, layanan tidak tersedia. Mohon pilih expedisi lain.');
+      }
     } else {
+      setSelectedCourier(courier === 32 ? 'SELF PICKUP' : null);
       setServiceOptions([]);
     }
   };
@@ -198,6 +262,11 @@ export default function SectionExpedition({ products }) {
     console.log(data);
   };
 
+  const handleOnFocuse = (value) => {
+    setOnFocuseSelectedCourier(!value);
+    setIsOpen(false);
+  };
+
   const handleSelect = (service) => {
     setSelectedService(service);
     setBiayaKirim(service?.price);
@@ -206,48 +275,79 @@ export default function SectionExpedition({ products }) {
     setIsOpen(false);
   };
 
+  console.log('ini selectedCourier', selectedCourier);
+
   return (
     <form onSubmit={handleSubmit(onSubmit)}>
       <div className='px-4 py-2'>
         <div className='flex justify-between items-center'>
           <div className='font-medium'>Pilih Ekspedisi: </div>
-          <div className='w-[250px]'>
-            <div className='flex items-center gap-x-4'>
-              <select
-                className={`form-input `}
-                onChange={onCourierChange}
-                onMouseDown={() => setOnFocuseSelectedCourier(true)}
-                required
-              >
-                {!isLoading ? (
-                  <>
-                    <option value='0'>Pilih Pengiriman</option>
-                    <option value='32'>SELF PICKUP</option>
-                    {couriers &&
-                      Object.values(couriers)?.map((expedisi) => (
-                        <option
-                          value={expedisi.courier_code}
-                          key={expedisi.courier_name}
-                        >
-                          {' '}
-                          {expedisi.courier_name}
-                        </option>
-                      ))}
-                  </>
-                ) : (
-                  <>
-                    <option disabled className='skeleton-option'>
-                      <Skeleton height={40} containerClassName='w-full' />
-                    </option>
-                    <option disabled className='skeleton-option'>
-                      <Skeleton height={40} containerClassName='w-full' />
-                    </option>
-                    <option disabled className='skeleton-option'>
-                      <Skeleton height={40} containerClassName='w-full' />
-                    </option>
-                  </>
-                )}
-              </select>
+          <div className='w-[350px] max'>
+            <div className='px-4 py-2'>
+              <div className='flex justify-between items-center'>
+                <div className='w-[450px]'>
+                  <div className='relative'>
+                    {/* Custom Select Input Field */}
+                    <div
+                      className='w-full p-2 border rounded-lg bg-white cursor-pointer'
+                      onClick={() => handleOnFocuse(onFocusSelectedCourier)}
+                    >
+                      {selectedCourier ? (
+                        <div className='flex justify-between'>
+                          <span>{selectedCourier}</span>
+                        </div>
+                      ) : (
+                        <span className='text-gray-500'>Pilih Expedisi</span>
+                      )}
+                    </div>
+
+                    {/* Dropdown Options */}
+                    {onFocusSelectedCourier && (
+                      <div className='absolute w-full bg-white border rounded-lg mt-1 shadow-lg z-10 max-h-[200px] overflow-y-auto'>
+                        {!isLoading ? (
+                          <>
+                            <div
+                              key={32}
+                              onClick={() => onCourierChange(32)}
+                              className='flex justify-between p-2 items-center hover:bg-gray-100 cursor-pointer'
+                            >
+                              <div>
+                                <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>
+                                </div>
+                                <span className='font-semibold'>
+                                  <Image
+                                    src={courier?.logo}
+                                    alt={courier?.courier?.courier_name}
+                                    width={50}
+                                    height={50}
+                                  />
+                                </span>
+                              </div>
+                            ))}
+                          </>
+                        ) : (
+                          <>
+                            <Skeleton height={40} containerClassName='w-full' />
+                            <Skeleton height={40} containerClassName='w-full' />
+                          </>
+                        )}
+                      </div>
+                    )}
+                  </div>
+                </div>
+              </div>
             </div>
             {checkoutValidation && (
               <span className='text-sm text-red-500'>
@@ -276,9 +376,9 @@ export default function SectionExpedition({ products }) {
         )}
       </div>
 
-      {selectedCourier &&
-        selectedCourier !== '32' &&
-        selectedCourier !== '0' && (
+      {serviceOptions.length > 0 && selectedCourier &&
+        selectedCourier !== 32 &&
+        selectedCourier !== 0 && (
           <div className='px-4 py-2'>
             <div className='flex justify-between items-center'>
               <div className='font-medium'>Tipe Layanan Ekspedisi: </div>
@@ -294,8 +394,9 @@ export default function SectionExpedition({ products }) {
                         <span>{selectedService.service_name}</span>
                         <span className='font-semibold'>
                           {currencyFormat(
-                            Math.round(parseInt(selectedService?.price * 1.1) / 1000) *
-                              1000
+                            Math.round(
+                              parseInt(selectedService?.price * 1.1) / 1000
+                            ) * 1000
                           )}
                         </span>
                       </div>
@@ -305,8 +406,6 @@ export default function SectionExpedition({ products }) {
                       </span>
                     )}
                   </div>
-
-                  {/* Dropdown Options */}
                   {isOpen && (
                     <div className='absolute w-full bg-white border rounded-lg mt-1 shadow-lg z-10'>
                       {serviceOptions.map((service) => (
@@ -328,8 +427,9 @@ export default function SectionExpedition({ products }) {
                           </div>
                           <span className='font-semibold'>
                             {currencyFormat(
-                              Math.round(parseInt(service?.price * 1.1) / 1000) *
-                                1000
+                              Math.round(
+                                parseInt(service?.price * 1.1) / 1000
+                              ) * 1000
                             )}
                           </span>
                         </div>
-- 
cgit v1.2.3


From bd4cdf2125f717875ba90e03893b319dd962f753 Mon Sep 17 00:00:00 2001
From: trisusilo48 <tri.susilo@altama.co.id>
Date: Sat, 18 Jan 2025 10:37:49 +0700
Subject: bittesip

---
 src/lib/checkout/components/SectionExpedition.jsx | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 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 8b59d210..5b4f6bfc 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -228,13 +228,10 @@ export default function SectionExpedition({ products }) {
     }
   );
 
-  console.log('ini response', data);
-
   useEffect(() => {
     if (data) {
       const couriers = reverseMappingCourier(listExpedisi, data?.data?.pricing);
       setCouriers(couriers);
-      console.log('ini scourier', couriers);
     }
   }, [data]);
 
@@ -249,7 +246,15 @@ export default function SectionExpedition({ products }) {
         setSelectedCourier(courier.courier.courier_code);
         setServiceOptions(Object.values(courier.courier.service_type));
       } else {
-        toast.error('Maaf, layanan tidak tersedia. Mohon pilih expedisi lain.');
+        if ((courier.label === 'GRAB' || courier.label === 'GOJEK') && !addressMaps) {
+          toast.error(
+            'Maaf, layanan kurir ' + courier.label + ' tidak tersedia. Karena Anda Belum Melakukan Pengaturan PinPoint Alamat Pegiriman.'
+          )
+        } else {
+          toast.error(
+            'Maaf, layanan tidak tersedia. Mohon pilih expedisi lain.'
+          );
+        }
       }
     } else {
       setSelectedCourier(courier === 32 ? 'SELF PICKUP' : null);
@@ -376,7 +381,8 @@ export default function SectionExpedition({ products }) {
         )}
       </div>
 
-      {serviceOptions.length > 0 && selectedCourier &&
+      {serviceOptions.length > 0 &&
+        selectedCourier &&
         selectedCourier !== 32 &&
         selectedCourier !== 0 && (
           <div className='px-4 py-2'>
-- 
cgit v1.2.3


From c26a0d026886e6f70ea3487b9d83a54d20b9c1e4 Mon Sep 17 00:00:00 2001
From: trisusilo48 <tri.susilo@altama.co.id>
Date: Tue, 28 Jan 2025 09:46:11 +0700
Subject: biteship

---
 src/lib/checkout/components/SectionExpedition.jsx | 59 +++++++++++++++++++----
 1 file changed, 50 insertions(+), 9 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 5b4f6bfc..d1844204 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -12,6 +12,9 @@ import { formatShipmentRange } from '../utils/functionCheckouit';
 import Image from 'next/image';
 import toast from 'react-hot-toast';
 
+import odooApi from '@/core/api/odooApi';
+import { getProductsSla } from '../api/checkoutApi';
+
 function mappingItems(products) {
   return products?.map((item) => ({
     name: item.parent.name,
@@ -19,16 +22,19 @@ function mappingItems(products) {
     value: item.price.priceDiscount,
     weight: item.weight * 1000,
     quantity: item.quantity,
-    canInstant: item.availableQuantity > item.quantity ? true : false,
   }));
 }
 
-function reverseMappingCourier(couriersOdoo, couriers) {
+function reverseMappingCourier(couriersOdoo, couriers, includeInstant = false) {
   // Buat peta courier berdasarkan nama courier dari couriers
   const courierMap = couriers.reduce((acc, item) => {
     const { courier_name, courier_code, courier_service_code } = item;
     const key = courier_name.toLowerCase();
 
+    if (!includeInstant && ['hours'].includes(item.shipment_duration_unit.toLowerCase())) {
+      return acc;
+    }
+
     if (!acc[key]) {
       acc[key] = {
         courier_name: item.courier_name,
@@ -166,6 +172,7 @@ export default function SectionExpedition({ products }) {
   const [selectedE, setIsOpenCourier] = useState(false);
   const [onFocusSelectedCourier, setOnFocuseSelectedCourier] = useState(false);
   const [couriers, setCouriers] = useState(null);
+  const [slaProducts, setSlaProducts] = useState(null);
 
   const {
     checkWeigth,
@@ -178,12 +185,13 @@ export default function SectionExpedition({ products }) {
     selectedService,
     setSelectedService,
     listExpedisi,
+    productSla,
+    setProductSla
   } = useCheckout();
 
   let destination = {};
   let items = mappingItems(products);
 
-  let notIncludeInstant = hasCanInstantFalse(items);
   if (addressMaps) {
     destination = {
       origin_latitude: -6.3031123,
@@ -197,6 +205,32 @@ export default function SectionExpedition({ products }) {
     };
   }
 
+  const fetchSlaProducts = async () => {
+    try {
+      const ids = products.map((p) => p.id).join(',')
+      const res = await odooApi('GET', `/api/v1/product/variants/sla?ids=${ids}`)
+
+      setSlaProducts(res);
+    } catch (error) {
+      console.error('Failed to fetch expedition rates:', error);
+    }
+  };
+
+  useEffect(() => {
+    fetchSlaProducts();
+  }, []);
+
+  useEffect(() => {
+    if (slaProducts) {
+      let productSla = slaProducts?.slaDuration
+      if(slaProducts.slaUnit === 'jam') {
+        productSla = 1
+      }
+      setProductSla(productSla);
+    }
+    console.log('ini slaProducts', slaProducts, productSla);
+  }, [slaProducts]);
+
   const fetchExpedition = async () => {
     let body = {
       ...destination,
@@ -230,7 +264,8 @@ export default function SectionExpedition({ products }) {
 
   useEffect(() => {
     if (data) {
-      const couriers = reverseMappingCourier(listExpedisi, data?.data?.pricing);
+      const instant = slaProducts?.includeInstant || false;
+      const couriers = reverseMappingCourier(listExpedisi, data?.data?.pricing, instant);
       setCouriers(couriers);
     }
   }, [data]);
@@ -246,10 +281,15 @@ export default function SectionExpedition({ products }) {
         setSelectedCourier(courier.courier.courier_code);
         setServiceOptions(Object.values(courier.courier.service_type));
       } else {
-        if ((courier.label === 'GRAB' || courier.label === 'GOJEK') && !addressMaps) {
+        if (
+          (courier.label === 'GRAB' || courier.label === 'GOJEK') &&
+          !addressMaps
+        ) {
           toast.error(
-            'Maaf, layanan kurir ' + courier.label + ' tidak tersedia. Karena Anda Belum Melakukan Pengaturan PinPoint Alamat Pegiriman.'
-          )
+            'Maaf, layanan kurir ' +
+              courier.label +
+              ' tidak tersedia. Karena Anda Belum Melakukan Pengaturan PinPoint Alamat Pegiriman.'
+          );
         } else {
           toast.error(
             'Maaf, layanan tidak tersedia. Mohon pilih expedisi lain.'
@@ -280,7 +320,7 @@ export default function SectionExpedition({ products }) {
     setIsOpen(false);
   };
 
-  console.log('ini selectedCourier', selectedCourier);
+  console.log('ini selectedCourier', couriers);
 
   return (
     <form onSubmit={handleSubmit(onSubmit)}>
@@ -427,7 +467,8 @@ export default function SectionExpedition({ products }) {
                             <p className='text-gray-600 text-sm'>
                               {formatShipmentRange(
                                 service.shipment_range,
-                                service.shipment_unit
+                                service.shipment_unit,
+                                productSla
                               )}
                             </p>
                           </div>
-- 
cgit v1.2.3


From fdb488651e864cf30f09fe2337187241ef649177 Mon Sep 17 00:00:00 2001
From: trisusilo48 <tri.susilo@altama.co.id>
Date: Sat, 1 Feb 2025 11:04:29 +0700
Subject: function check holidays

---
 src/lib/checkout/components/SectionExpedition.jsx | 8 ++++++++
 1 file changed, 8 insertions(+)

(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 d1844204..a00858e5 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -80,6 +80,14 @@ function reverseMappingCourier(couriersOdoo, couriers, includeInstant = false) {
   });
 }
 
+
+function isHiloday(){
+  const today = new Date();
+  const day = today.getDay();
+
+  return day === 6 || day === 7
+}
+
 function mappingCourier(couriersOdoo, couriers, notIncludeInstant = false) {
   const validCourierMap = couriersOdoo.reduce((acc, courier) => {
     acc[courier.label.toLowerCase()] = courier.carrierId;
-- 
cgit v1.2.3


From 58601bc17b6f0516eee9c36aa36e39f1dea3ad77 Mon Sep 17 00:00:00 2001
From: trisusilo48 <tri.susilo@altama.co.id>
Date: Wed, 26 Feb 2025 10:47:58 +0700
Subject: bitehsip

---
 src/lib/checkout/components/SectionExpedition.jsx | 23 +++++++----------------
 1 file changed, 7 insertions(+), 16 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 a00858e5..b261cae0 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -49,7 +49,7 @@ function reverseMappingCourier(couriersOdoo, couriers, includeInstant = false) {
       shipment_range: item.shipment_duration_range,
       shipment_unit: item.shipment_duration_unit,
       price: item.price,
-      service_type: item.service_type,
+      service_type: courier_service_code,
       description: item.description,
     };
 
@@ -81,13 +81,6 @@ function reverseMappingCourier(couriersOdoo, couriers, includeInstant = false) {
 }
 
 
-function isHiloday(){
-  const today = new Date();
-  const day = today.getDay();
-
-  return day === 6 || day === 7
-}
-
 function mappingCourier(couriersOdoo, couriers, notIncludeInstant = false) {
   const validCourierMap = couriersOdoo.reduce((acc, courier) => {
     acc[courier.label.toLowerCase()] = courier.carrierId;
@@ -144,9 +137,6 @@ function mappingCourier(couriersOdoo, couriers, notIncludeInstant = false) {
   }, {});
 }
 
-function hasCanInstantFalse(items) {
-  return items.some((item) => item.canInstant === false);
-}
 
 // interface CourierService {
 //   courier_name: string;
@@ -181,6 +171,7 @@ export default function SectionExpedition({ products }) {
   const [onFocusSelectedCourier, setOnFocuseSelectedCourier] = useState(false);
   const [couriers, setCouriers] = useState(null);
   const [slaProducts, setSlaProducts] = useState(null);
+  const [addHolidays, setAddHolidays] = useState(0);
 
   const {
     checkWeigth,
@@ -194,7 +185,8 @@ export default function SectionExpedition({ products }) {
     setSelectedService,
     listExpedisi,
     productSla,
-    setProductSla
+    setProductSla,
+    setSelectedCourierId
   } = useCheckout();
 
   let destination = {};
@@ -217,7 +209,6 @@ export default function SectionExpedition({ products }) {
     try {
       const ids = products.map((p) => p.id).join(',')
       const res = await odooApi('GET', `/api/v1/product/variants/sla?ids=${ids}`)
-
       setSlaProducts(res);
     } catch (error) {
       console.error('Failed to fetch expedition rates:', error);
@@ -230,7 +221,7 @@ export default function SectionExpedition({ products }) {
 
   useEffect(() => {
     if (slaProducts) {
-      let productSla = slaProducts?.slaDuration
+      let productSla = slaProducts?.slaTotal
       if(slaProducts.slaUnit === 'jam') {
         productSla = 1
       }
@@ -282,11 +273,13 @@ export default function SectionExpedition({ products }) {
     setIsOpen(false);
     setOnFocuseSelectedCourier(false);
     const courier = code;
+    console.log('ini courier', courier, couriers);
     setSelectedService(null);
     setBiayaKirim(0);
     if (courier !== 0 && courier !== 32) {
       if (courier.courier) {
         setSelectedCourier(courier.courier.courier_code);
+        setSelectedCourierId(courier.carrierId)
         setServiceOptions(Object.values(courier.courier.service_type));
       } else {
         if (
@@ -328,8 +321,6 @@ export default function SectionExpedition({ products }) {
     setIsOpen(false);
   };
 
-  console.log('ini selectedCourier', couriers);
-
   return (
     <form onSubmit={handleSubmit(onSubmit)}>
       <div className='px-4 py-2'>
-- 
cgit v1.2.3


From f88f457fd1b91298ea8a7f9f396e49660a81e276 Mon Sep 17 00:00:00 2001
From: trisusilo48 <tri.susilo@altama.co.id>
Date: Mon, 17 Mar 2025 09:06:47 +0700
Subject: handle bug service type kurir

---
 src/lib/checkout/components/SectionExpedition.jsx | 47 ++++++++++++++++-------
 1 file changed, 33 insertions(+), 14 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 b261cae0..22d8df32 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -31,7 +31,10 @@ function reverseMappingCourier(couriersOdoo, couriers, includeInstant = false) {
     const { courier_name, courier_code, courier_service_code } = item;
     const key = courier_name.toLowerCase();
 
-    if (!includeInstant && ['hours'].includes(item.shipment_duration_unit.toLowerCase())) {
+    if (
+      !includeInstant &&
+      ['hours'].includes(item.shipment_duration_unit.toLowerCase())
+    ) {
       return acc;
     }
 
@@ -80,7 +83,6 @@ function reverseMappingCourier(couriersOdoo, couriers, includeInstant = false) {
   });
 }
 
-
 function mappingCourier(couriersOdoo, couriers, notIncludeInstant = false) {
   const validCourierMap = couriersOdoo.reduce((acc, courier) => {
     acc[courier.label.toLowerCase()] = courier.carrierId;
@@ -137,7 +139,6 @@ function mappingCourier(couriersOdoo, couriers, notIncludeInstant = false) {
   }, {});
 }
 
-
 // interface CourierService {
 //   courier_name: string;
 //   courier_code: string;
@@ -172,6 +173,7 @@ export default function SectionExpedition({ products }) {
   const [couriers, setCouriers] = useState(null);
   const [slaProducts, setSlaProducts] = useState(null);
   const [addHolidays, setAddHolidays] = useState(0);
+  const [savedServiceOptions, setSavedServiceOptions] = useState([]);
 
   const {
     checkWeigth,
@@ -186,7 +188,7 @@ export default function SectionExpedition({ products }) {
     listExpedisi,
     productSla,
     setProductSla,
-    setSelectedCourierId
+    setSelectedCourierId,
   } = useCheckout();
 
   let destination = {};
@@ -207,8 +209,15 @@ export default function SectionExpedition({ products }) {
 
   const fetchSlaProducts = async () => {
     try {
-      const ids = products.map((p) => p.id).join(',')
-      const res = await odooApi('GET', `/api/v1/product/variants/sla?ids=${ids}`)
+      let productsMapped = products.map((item) => ({
+        id: item.id,
+        quantity: item.quantity,
+      }));
+
+      let data = {
+        products: JSON.stringify(productsMapped),
+      }
+      const res = await odooApi('POST', `/api/v1/product/variants/sla`, data);
       setSlaProducts(res);
     } catch (error) {
       console.error('Failed to fetch expedition rates:', error);
@@ -221,13 +230,12 @@ export default function SectionExpedition({ products }) {
 
   useEffect(() => {
     if (slaProducts) {
-      let productSla = slaProducts?.slaTotal
-      if(slaProducts.slaUnit === 'jam') {
-        productSla = 1
+      let productSla = slaProducts?.slaTotal;
+      if (slaProducts.slaUnit === 'jam') {
+        productSla = 1;
       }
       setProductSla(productSla);
     }
-    console.log('ini slaProducts', slaProducts, productSla);
   }, [slaProducts]);
 
   const fetchExpedition = async () => {
@@ -264,7 +272,11 @@ export default function SectionExpedition({ products }) {
   useEffect(() => {
     if (data) {
       const instant = slaProducts?.includeInstant || false;
-      const couriers = reverseMappingCourier(listExpedisi, data?.data?.pricing, instant);
+      const couriers = reverseMappingCourier(
+        listExpedisi,
+        data?.data?.pricing,
+        instant
+      );
       setCouriers(couriers);
     }
   }, [data]);
@@ -273,13 +285,12 @@ export default function SectionExpedition({ products }) {
     setIsOpen(false);
     setOnFocuseSelectedCourier(false);
     const courier = code;
-    console.log('ini courier', courier, couriers);
     setSelectedService(null);
     setBiayaKirim(0);
     if (courier !== 0 && courier !== 32) {
       if (courier.courier) {
         setSelectedCourier(courier.courier.courier_code);
-        setSelectedCourierId(courier.carrierId)
+        setSelectedCourierId(courier.carrierId);
         setServiceOptions(Object.values(courier.courier.service_type));
       } else {
         if (
@@ -296,6 +307,7 @@ export default function SectionExpedition({ products }) {
             'Maaf, layanan tidak tersedia. Mohon pilih expedisi lain.'
           );
         }
+        setServiceOptions([]);
       }
     } else {
       setSelectedCourier(courier === 32 ? 'SELF PICKUP' : null);
@@ -321,6 +333,12 @@ export default function SectionExpedition({ products }) {
     setIsOpen(false);
   };
 
+  useEffect(() => {
+  if (serviceOptions.length > 0) {
+    setSavedServiceOptions(serviceOptions);
+  }
+}, [serviceOptions]);
+
   return (
     <form onSubmit={handleSubmit(onSubmit)}>
       <div className='px-4 py-2'>
@@ -420,7 +438,8 @@ export default function SectionExpedition({ products }) {
         )}
       </div>
 
-      {serviceOptions.length > 0 &&
+      {(serviceOptions.length > 0 ||
+        selectedService )&&
         selectedCourier &&
         selectedCourier !== 32 &&
         selectedCourier !== 0 && (
-- 
cgit v1.2.3


From 71ca9d6c85871b6bcb2976ed4911032aab4d32e7 Mon Sep 17 00:00:00 2001
From: trisusilo48 <tri.susilo@altama.co.id>
Date: Thu, 24 Apr 2025 13:53:32 +0700
Subject: fixing revisi renca

---
 src/lib/checkout/components/SectionExpedition.jsx | 16 ++++------------
 1 file changed, 4 insertions(+), 12 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 22d8df32..b017c82e 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -29,7 +29,7 @@ function reverseMappingCourier(couriersOdoo, couriers, includeInstant = false) {
   // Buat peta courier berdasarkan nama courier dari couriers
   const courierMap = couriers.reduce((acc, item) => {
     const { courier_name, courier_code, courier_service_code } = item;
-    const key = courier_name.toLowerCase();
+    const key = courier_code.toLowerCase();
 
     if (
       !includeInstant &&
@@ -165,14 +165,11 @@ function mappingCourier(couriersOdoo, couriers, notIncludeInstant = false) {
 
 export default function SectionExpedition({ products }) {
   const { addressMaps, coordinate, postalCode } = useAddress();
-  const { control, handleSubmit } = useForm();
   const [serviceOptions, setServiceOptions] = useState([]);
   const [isOpen, setIsOpen] = useState(false);
-  const [selectedE, setIsOpenCourier] = useState(false);
   const [onFocusSelectedCourier, setOnFocuseSelectedCourier] = useState(false);
   const [couriers, setCouriers] = useState(null);
   const [slaProducts, setSlaProducts] = useState(null);
-  const [addHolidays, setAddHolidays] = useState(0);
   const [savedServiceOptions, setSavedServiceOptions] = useState([]);
 
   const {
@@ -270,8 +267,8 @@ export default function SectionExpedition({ products }) {
   );
 
   useEffect(() => {
+    const instant = slaProducts?.includeInstant || false;
     if (data) {
-      const instant = slaProducts?.includeInstant || false;
       const couriers = reverseMappingCourier(
         listExpedisi,
         data?.data?.pricing,
@@ -279,7 +276,7 @@ export default function SectionExpedition({ products }) {
       );
       setCouriers(couriers);
     }
-  }, [data]);
+  }, [data, slaProducts]);
 
   const onCourierChange = (code) => {
     setIsOpen(false);
@@ -315,11 +312,6 @@ export default function SectionExpedition({ products }) {
     }
   };
 
-  const onSubmit = (data) => {
-    1;
-    console.log(data);
-  };
-
   const handleOnFocuse = (value) => {
     setOnFocuseSelectedCourier(!value);
     setIsOpen(false);
@@ -340,7 +332,7 @@ export default function SectionExpedition({ products }) {
 }, [serviceOptions]);
 
   return (
-    <form onSubmit={handleSubmit(onSubmit)}>
+    <form >
       <div className='px-4 py-2'>
         <div className='flex justify-between items-center'>
           <div className='font-medium'>Pilih Ekspedisi: </div>
-- 
cgit v1.2.3


From 5077cf5ac59e15529de1abab43b4a49a4722bd2d Mon Sep 17 00:00:00 2001
From: trisusilo48 <tri.susilo@altama.co.id>
Date: Mon, 28 Apr 2025 08:46:44 +0700
Subject: handlig cache sla pengiriman

---
 src/lib/checkout/components/SectionExpedition.jsx | 4 ++--
 1 file changed, 2 insertions(+), 2 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 b017c82e..40084048 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -32,8 +32,8 @@ function reverseMappingCourier(couriersOdoo, couriers, includeInstant = false) {
     const key = courier_code.toLowerCase();
 
     if (
-      !includeInstant &&
-      ['hours'].includes(item.shipment_duration_unit.toLowerCase())
+      !includeInstant && (['hours'].includes(item.shipment_duration_unit.toLowerCase()) || item.service_type == 'same_day')
+      
     ) {
       return acc;
     }
-- 
cgit v1.2.3


From 5754fd0a95bc72f0e97e6af2d246f4d14a45bf9f Mon Sep 17 00:00:00 2001
From: "Indoteknik ." <andrifebriyadiputra@gmail.com>
Date: Mon, 16 Jun 2025 11:14:28 +0700
Subject: (andri) fix self pick up checkout

---
 src/lib/checkout/components/SectionExpedition.jsx | 1 +
 1 file changed, 1 insertion(+)

(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 40084048..fdad04ce 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -308,6 +308,7 @@ export default function SectionExpedition({ products }) {
       }
     } else {
       setSelectedCourier(courier === 32 ? 'SELF PICKUP' : null);
+      setSelectedCourierId(courier);
       setServiceOptions([]);
     }
   };
-- 
cgit v1.2.3


From 6415e9c36b00c38089d2676a2e95ab7a165c99ea Mon Sep 17 00:00:00 2001
From: "Indoteknik ." <andrifebriyadiputra@gmail.com>
Date: Mon, 16 Jun 2025 16:31:44 +0700
Subject: <miqdad> fix tidak bisa checkout barang bundling

---
 src/lib/checkout/components/SectionExpedition.jsx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(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 fdad04ce..7a02c6e9 100644
--- a/src/lib/checkout/components/SectionExpedition.jsx
+++ b/src/lib/checkout/components/SectionExpedition.jsx
@@ -17,7 +17,8 @@ import { getProductsSla } from '../api/checkoutApi';
 
 function mappingItems(products) {
   return products?.map((item) => ({
-    name: item.parent.name,
+    // name: item.parent.name || item?.name || 'Unknown Product',
+    name:  item?.name,
     description: `${item.code} - ${item.name}`,
     value: item.price.priceDiscount,
     weight: item.weight * 1000,
-- 
cgit v1.2.3

