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 (
{/*JSON.stringify(carts)*/} 0 ? '1px solid #ede9e9':'none', borderRadius:4}}>
{Object.values(groupedPromotions)?.length>0 &&
{config?.lang=='vi'?"1. Giá":"1. Price"}

{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"}

} {Object.values(groupedPromotions).map((promotion, p_index) => ( {/*promotion.id*/} { (config?.lang=='vi'?(promotion.name_vi || promotion.name_en || "Sản phẩm"):(promotion.name_en ||promotion.name_vi || "Products"))} {promotion?.items_apply.map((item, index) => (
handleSelectProduct(item.product_info)} style={{ padding: '1px 0', borderBottom: '0px solid #e0e0e0' }}> {/* Dòng riêng cho item_code và description */}
<> {config?.lang=='vi' ? <>
{itemCounter++} . {item.item_code} - {item.description_vi[0] || item.description_en[0] || item?.product_info?.product?.description} {item?.return_tx_no? (Return No:{item?.return_tx_no}):<>}
: <>
{itemCounter++} . {item.item_code} - {item.description_en[0] || item.description_vi[0] || item?.product_info?.product?.description} {item?.return_tx_no? (Return No:{item?.return_tx_no}):<>}
}
{/* Flexbox cho các thông tin khác */}
{commonFunc.formatNumber (item.price) }

{item.price - (item.promotion_price - (item?.discount_value ||0)) != item.price ? commonFunc.formatNumber (item.price - ( item.promotion_price - (item?.discount_value ||0))) : ""}

{ item.line_type == 'S' ? <> {handleChangeQty('-',item.item_code,1,(item.line_type || 'S'))}} style={{ fontSize:25, paddingLeft:5 , color:'gray', float:'left'}} tabIndex = {itemCounter*4+5} refCtl={(el) => (decrementButtonsRef.current[item?.order] = el)} /> {item.qty} {handleChangeQty('+',item.item_code,1,(item.line_type || 'S'))}} style={{ fontSize:25, paddingLeft:5 , color:'green', float:'right'}} tabIndex = {itemCounter*4+5} refCtl={(el) => (incrementButtonsRef.current[item?.order] = el)} /> : <> {handleChangeQty('-',item.item_code,1,(item.line_type || 'S'))}} style={{ fontSize:25, paddingLeft:5 , color:'gray', float:'left'}} tabIndex = {itemCounter*4+5} /> {item.qty} {handleChangeQty('+',item.item_code,1,(item.line_type || 'S'))}} style={{ fontSize:25, paddingLeft:5 , color:'green', float:'right'}} tabIndex = {itemCounter*4+5}/> }

{ commonFunc.formatNumber (item.qty* (item?.promotion_price- (item?.discount_value ||0)))}

{ (item?.line_type!='R') ? handleShowHotPromoLine(promotion.id,item?.item_code, item?.promotion_price)} style={{ fontSize:25, paddingLeft:10 , color:'green', float:'left'}} tabIndex = {itemCounter*4+5} refCtl={(el) => (editButtonsRef.current[item?.order] = el)} />: <> } handleChangeQty('-',item?.item_code,item.qty, (item.line_type || 'S'))} style={{ fontSize:25, paddingRight:0 , color:'red', float:'right'}} tabIndex = {itemCounter*4+5} refCtl={(el) => (deleteButtonsRef.current[item?.order] = el)} />
))}
))} {Object.values(groupedPromotions)?.length>0 &&
Σ {commonFunc.formatNumber(total?.totalAmount)}

{commonFunc.formatNumber(total?.totalAmount-total?.totalExtension)}

{commonFunc.formatNumber(total?.totalQty)}

{commonFunc.formatNumber(total?.totalExtension)}

5.Action

}
setShowModalHotPromoLine(false)} />
) }