const ProductCart = (props)=>{ const {config, baskets, setBaskets, setProductSelected,handleChangeQty, carts, setCarts, userInfo, updateShoppingBasket, basketIconClick, returnNo, setTransactionReturn, showCart=false} = props // chắc chắn lỗi ở getCookie ở đâu đó const { Row, Col, Card, Form } = ReactBootstrap const [loading, setLoading] = useState(false) const [itemSelected, setItemSelected] = useState({promo_id:null, item_code:""}) const [showModalPrint, setShowModalPrint] =useState(false) const [total, setTotal] = useState({}) const [groupedPromotions, setGroupedPromotions] = useState({}); const [showModalHotPromoLine,setShowModalHotPromoLine] = useState(false) const [applyPromotion, setApplyPromotion] = useState(true) const handleShowModalPrint=()=>{ setShowModalPrint(true) } const handleSelectProduct=(productInfo)=>{ setProductSelected(productInfo) } useEffect(() => { // Set focus vào sản phẩm đầu tiên khi component mount if (itemsRef.current[selectedRef.current]){ itemsRef.current[selectedRef.current]?.focus(); } const strBasket = commonFunc.getCookies('baskets'); if (strBasket) { try { const jBasket = JSON.parse(strBasket); // Chỉ set nếu baskets hiện tại đang trống if (!baskets || !baskets.items || baskets.items.length === 0) { setBaskets({ ...jBasket, basket: { ...jBasket.basket, reload: true } }); } } catch (e) { console.error("Lỗi parse basket cookie"); } } }, []); useEffect(() => { if (!userInfo || !baskets) return; // Tránh xử lý nếu baskets đang trống (để tránh xung đột với logic Init ở trên) if (baskets?.items?.length > 0) { // Gọi API cần thiết if (returnNo && returnNo > 0) { fetchReturnBill(); } else { fetchPromotionsApply(); } // Tạo bản clone để xử lý, tránh mutate trực tiếp state let newBaskets = JSON.parse(JSON.stringify(baskets)); // Xóa thông tin thừa trước khi lưu cookie newBaskets.items.forEach(item => delete item.product_info); // Cập nhật thông tin User if (userInfo?.internal_user === "0") { if (!newBaskets.basket) newBaskets.basket = {}; newBaskets.basket.cust_code = userInfo?.reference_code ?? null; } // Đảm bảo có basket_id if (!newBaskets?.basket?.basket_id) { newBaskets.basket = { ...newBaskets.basket, basket_id: Date.now(), reload: false }; } else { newBaskets.basket.reload = false; } // CHỈ LƯU VÀO COOKIE, HẠN CHẾ SETBASKETS Ở ĐÂY commonFunc.setCookies('baskets', JSON.stringify(newBaskets), undefined); // Cập nhật icon giỏ hàng const totalQty = baskets.items.reduce((sum, item) => sum + (item.qty || 0), 0); if (updateShoppingBasket) { updateShoppingBasket(totalQty, basketIconClick); } } else { // Nếu length == 0 thực sự thì mới xóa cookie if (baskets?.items) { commonFunc.setCookies('baskets', {}, -1); } // Cập nhật icon giỏ hàng const totalQty = baskets.items.reduce((sum, item) => sum + (item.qty || 0), 0); if (updateShoppingBasket) { updateShoppingBasket(totalQty, basketIconClick); } setCarts([]) } }, [baskets?.items?.length,baskets?.items, baskets?.basket?.basket_id, userInfo, applyPromotion]) //[baskets?.items?.length,baskets?.items?.reduce((sum, item) => sum + (item.qty || 0), 0), baskets?.basket?.basket_id, userInfo]) const fetchPromotionsApply = async () => { try { setLoading(true) const url =`/api/apply-promotions` const dataRequest = { baskets: baskets, branch_no:userInfo?.branch_no, apply_promotion:applyPromotion } if (baskets?.items?.length==0){ setCarts([]) return } const resultObj = await commonApi.APIPOSTByURL(url, dataRequest, config) if (resultObj.status == 200){ let dataTmp = resultObj?.data dataTmp=updateDiscountTo(baskets,dataTmp) calculateSums(dataTmp) setCarts(dataTmp) } //console.log(dataInit ) } catch (e) { console.log("ERROR apply-promotions") }finally{ setLoading(false) } }; const fetchReturnBill = async () => { try { if (!returnNo){ alert('Return No not found!!') return } setLoading(true) const url =`/api/get-pos-transaction-by-sale-tx-no?sale_tx_no=${returnNo.trim()}&is_return=1` if (baskets?.items?.length==0){ setCarts([]) return } const resultObj = await commonApi.APIGETByURL(url, config) if (resultObj.status == 200){ let dataTmp = resultObj?.data setTransactionReturn(dataTmp) setCarts(dataTmp?.carts || []) } //console.log(dataInit ) } catch (e) { console.log("ERROR get-carts-by-return-bill") }finally{ setLoading(false) } }; useEffect(() => { const handleLoad = () => { // Thực hiện các tác vụ sau khi trang đã load const buttons = document.querySelectorAll('button[name="select_item"]'); if (buttons.length > 0) { // Kiểm tra xem có phần tử nào có class 'product-detail' không const productDetailExists = document.querySelector('.product-detail'); if (productDetailExists == null) { // Trigger sự kiện click cho button đầu tiên buttons[0].click(); } } }; setGroupedPromotions(groupedPromotionsTmp) // Gọi hàm handleLoad khi component được mount handleLoad(); let product_info = null const searchStr = location.pathname.replace('/products/','') const foundItem = carts?.flatMap(cart => cart.items_apply) // Gom tất cả items_apply của các cart lại .find(item => item.item_code === searchStr || item.product_info?.product?.slug === searchStr ); if (foundItem){ product_info = foundItem }else{ product_info = carts?.length >0 ? carts[0]?.items_apply[0]: null } if (showCart==true){ setProductSelected(product_info?.product_info) } // Nếu bạn muốn lắng nghe sự kiện load của window window.addEventListener('load', handleLoad); // Cleanup: Gỡ sự kiện khi component unmount return () => { window.removeEventListener('load', handleLoad); }; }, [carts]); // Chạy một lần khi component mount const updateDiscountTo = (baskets, dataTmp) => { // Duyệt qua từng item trong baskets.items baskets?.items?.forEach(basketItem => { const { item_code, line_discount } = basketItem; // Duyệt qua từng line_discount line_discount?.forEach(discount => { const { promo_id, discount_value } = discount; // Tìm item trong dataTmp tương ứng với promo_id và item_code const dataItem = dataTmp.find(item => item.id === promo_id); if (dataItem) { // Tìm items_apply trong dataItem const applyItem = dataItem?.items_apply.find(apply => apply.item_code === item_code); if (applyItem) { // Cập nhật discount_value applyItem.discount_value = discount_value; applyItem.extension = applyItem.extension - applyItem.qty*discount_value; } } }); }); // Duyệt lại dataTmp và cập nhật discount_value thành 0 nếu không tồn tại dataTmp.forEach(dataItem => { dataItem?.items_apply.forEach(applyItem => { const hasDiscount = baskets?.items?.some(basketItem => basketItem?.line_discount?.some(discount => discount.promo_id === dataItem.id && applyItem.item_code === basketItem.item_code ) ); if (!hasDiscount) { applyItem.discount_value = 0; } }); }); return dataTmp; // Trả về dataTmp đã được cập nhật }; function calculateSums(arr) { let totalAmount = 0; let totalExtension = 0; let totalQty =0; arr.forEach(promotion => { promotion?.items_apply.forEach(item => { totalAmount += item.qty * item.price; totalExtension += item.qty * (item.promotion_price - (item?.discount_value||0)); totalQty+=item.qty }); }); const total = { totalAmount: totalAmount, totalExtension, totalQty:totalQty }; setTotal(total) } const groupedPromotionsTmp = carts?.reduce((acc, promotion) => { const name = promotion.name_vi || promotion.name_en; if (!acc[name]) { acc[name] = { ...promotion, items_apply: [] }; } acc[name].items_apply = acc[name].items_apply.concat(promotion.items_apply); return acc; }, {}); let counter = 1; // Khởi tạo bộ đếm Object.values(groupedPromotions).forEach(promotion => { promotion.items_apply.forEach(item => { item.order = counter++; // Gán số thứ tự cho từng item }); }); const handleShowHotPromoLine =(promoId,itemCode, promotion_price)=>{ setItemSelected({promo_id:promoId, item_code:itemCode,promotion_price:promotion_price}) setShowModalHotPromoLine(true) } let itemCounter =1; const decrementButtonsRef = useRef([]); const itemsRef = useRef([]); const incrementButtonsRef = useRef([]); const deleteButtonsRef = useRef([]); const editButtonsRef = useRef([]); const selectedRef = useRef(0); // Lưu trữ chỉ số dòng được chọn let currentColumn = 'item_code' let newIndex=-1; const handleKeyDown = (event) => { const { key } = event; // Xử lý phím Tab if (key === 'Tab') { event.preventDefault(); // Ngăn hành vi mặc định } // Xử lý phím di chuyển if (key === 'ArrowUp' || key === 'ArrowDown' || key === 'ArrowRight' || key === 'ArrowLeft') { event.preventDefault(); // Ngăn hành vi mặc định const activeItemIndex = selectedRef.current; if (activeItemIndex !== undefined) { if (key === 'ArrowUp') { newIndex = activeItemIndex > 0 ? activeItemIndex - 1 : 0; // Di chuyển lên } else if (key === 'ArrowDown') { newIndex = activeItemIndex < itemsRef.current.length - 1 ? activeItemIndex + 1 : itemsRef.current.length - 1; // Di chuyển xuống } if (key === 'ArrowRight') { if (currentColumn=='item_code'){ currentColumn='decrement' }else if (currentColumn=='decrement'){ currentColumn='increment' }else if (currentColumn=='increment'){ currentColumn='edit' }else if (currentColumn=='edit'){ currentColumn='delete' } } else if (key === 'ArrowLeft') { if (currentColumn=='delete'){ currentColumn='edit' }else if (currentColumn=='edit'){ currentColumn='increment' }else if (currentColumn=='increment'){ currentColumn='decrement' }else if (currentColumn=='decrement'){ currentColumn='item_code' } } // Cập nhật chỉ số được chọn và focus đến hàng mới selectedRef.current = newIndex; if (currentColumn=='item_code'){ if (itemsRef.current[newIndex]){ itemsRef.current[newIndex].focus(); // Focus vào item mới } }else if (currentColumn=='increment'){ if (incrementButtonsRef.current[newIndex]){ incrementButtonsRef.current[newIndex].focus(); // Focus vào item mới }else{ if (key=='ArrowDown'){ if (incrementButtonsRef.current[newIndex+1]){ newIndex=newIndex+1 incrementButtonsRef.current[newIndex].focus(); // Focus vào item mới } }else if (key=='ArrowUp'){ if (incrementButtonsRef.current[newIndex-1]){ newIndex=newIndex-1 incrementButtonsRef.current[newIndex].focus(); // Focus vào item mới } } } }else if (currentColumn=='decrement'){ if (decrementButtonsRef.current[newIndex]){ decrementButtonsRef.current[newIndex].focus(); // Focus vào item mới }else{ if (key=='ArrowDown'){ if (decrementButtonsRef.current[newIndex+1]){ newIndex=newIndex+1 decrementButtonsRef.current[newIndex].focus(); // Focus vào item mới } }else if (key=='ArrowUp'){ if (decrementButtonsRef.current[newIndex-1]){ newIndex=newIndex-1 decrementButtonsRef.current[newIndex].focus(); // Focus vào item mới } } } }else if (currentColumn=='edit'){ if(editButtonsRef.current[newIndex]){ editButtonsRef.current[newIndex].focus(); // Focus vào item mới } }else if (currentColumn=='delete'){ if(deleteButtonsRef.current[newIndex]){ deleteButtonsRef.current[newIndex].focus(); // Focus vào item mới } } } } }; const handleApplyPromotionChange = (e) => { setApplyPromotion(e.target.checked); }; return (
{config?.lang=='vi'?"2. KM":"2. Promo"}
{config?.lang=='vi'?"3. SL":"3. Q.ty"}
{config?.lang=='vi'?"4. Tổng":"4. Total Amt"}
{config?.lang=='vi'?"5. Func":"5. Func"}
{item.price - (item.promotion_price - (item?.discount_value ||0)) != item.price ? commonFunc.formatNumber (item.price - ( item.promotion_price - (item?.discount_value ||0))) : ""}
{ commonFunc.formatNumber (item.qty* (item?.promotion_price- (item?.discount_value ||0)))}
{commonFunc.formatNumber(total?.totalAmount-total?.totalExtension)}
{commonFunc.formatNumber(total?.totalQty)}
{commonFunc.formatNumber(total?.totalExtension)}
5.Action