phx-react
Version:
PHX REACT
273 lines • 13.6 kB
JavaScript
import React, { useEffect, useRef } from 'react';
import { useState } from 'react';
import { MagnifyingGlassIcon } from '@heroicons/react/24/solid';
import ProductTable from './product-table';
import { countAllBundleAndProductQuery, getListBundleQuery, getListProductQuery } from './query';
import { caculateBundlePrice, caculateProductPrice } from './store-helper';
import PHXFuncGetLoggedInfo from '../Func/getLoginInfo';
import { PHXClientQueryV3 } from '../Func/GRPC/PHXGrpcClientV3';
import { PHXModal } from '../Modal';
import { PHXButton } from '../Button';
import { PHXBannerWithCard } from '../BannerWithCard/BannerWithCard';
import { PHXSkeleton } from '../Skeleton';
import { PHXEmptyRecord } from '../EmptyRecord';
export default function PHXStoreProduct({ show, setShow, schoolYearId, submitLoading = false, handleSubmit, isVerifyProjectCode = false, isInCampaign = false, }) {
const userInfo = PHXFuncGetLoggedInfo();
const [addNewData, setAddNewData] = useState([]);
const [initLoading, setInitLoading] = useState(true);
const scrollRef = useRef(null);
const [currPage, setCurrPage] = useState(0);
const [fetchMoreLoading, setFetchMoreLoading] = useState(false);
const [searchValue, setSearchValue] = useState('');
const [searchLoading, setSearchLoading] = useState(false);
const [checkedList, setCheckedList] = useState([]);
const [countAll, setCountAll] = useState(0);
const [showModalSelected, setShowModalSelected] = useState(false);
const [isHaveMore, setIsHaveMore] = useState({
product: true,
bundle: true,
});
const limit = 30;
function onHideModal() {
setCheckedList([]);
setAddNewData([]);
setInitLoading(true);
setCurrPage(0);
setIsHaveMore({
product: true,
bundle: true,
});
setSearchValue('');
setShow(false);
}
const handleCheckData = (productIndex) => {
const clone = [...addNewData];
const isChecked = addNewData[productIndex].checked;
clone[productIndex].checked = !isChecked;
if (isChecked) {
const cloneChecked = [...checkedList];
const filterChecked = cloneChecked.filter((item) => {
if (addNewData[productIndex].product_id) {
return item.product_id !== addNewData[productIndex].product_id;
}
else {
return item.bundle_id !== addNewData[productIndex].bundle_id;
}
});
setCheckedList(filterChecked);
}
else {
setCheckedList((pre) => [...pre, addNewData[productIndex]]);
}
setAddNewData(clone);
};
const getBundle = async () => {
try {
const { data: { store_bundle }, } = await PHXClientQueryV3({
query: getListBundleQuery(searchValue || '', isInCampaign),
variables: {
school_id: userInfo === null || userInfo === void 0 ? void 0 : userInfo.school_id,
school_year_id: schoolYearId || 0,
limit,
offset: currPage * limit,
},
isDelay: false,
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const formatBundle = store_bundle.map((bundle) => {
return {
...bundle,
checked: checkedList.some((item) => item.bundle_id === bundle.bundle_id),
price: caculateBundlePrice(bundle.store_bundle_products, bundle.price_type),
};
});
setAddNewData((pre) => [...pre, ...formatBundle]);
setIsHaveMore((pre) => ({
...pre,
bundle: !(formatBundle.length < limit),
}));
return formatBundle;
}
catch (e) {
console.log(e);
return [];
}
};
const getProduct = async () => {
try {
const { data: { store_product }, } = await PHXClientQueryV3({
query: getListProductQuery(searchValue || '', isInCampaign),
variables: {
school_id: userInfo === null || userInfo === void 0 ? void 0 : userInfo.school_id,
school_year_id: schoolYearId || 0,
limit,
offset: currPage * limit,
},
isDelay: false,
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const formatProduct = store_product.map((product) => {
return {
...product,
checked: checkedList.some((item) => item.product_id === product.product_id),
price: caculateProductPrice(product),
};
});
setAddNewData((pre) => [...pre, ...formatProduct]);
setIsHaveMore((pre) => ({
...pre,
product: !(formatProduct.length < limit),
}));
return formatProduct;
}
catch (e) {
console.log(e);
return [];
}
};
const handleCountAll = async () => {
try {
const { data: { store_product_aggregate, store_bundle_aggregate }, } = await PHXClientQueryV3({
query: countAllBundleAndProductQuery(isInCampaign),
variables: {
school_id: userInfo === null || userInfo === void 0 ? void 0 : userInfo.school_id,
},
});
setCountAll(store_product_aggregate.aggregate.count + store_bundle_aggregate.aggregate.count);
}
catch (e) {
console.log(e);
}
};
const getData = async () => {
try {
if (isHaveMore.product || searchValue) {
await getProduct();
}
if (isHaveMore.bundle || searchValue) {
await getBundle();
}
}
catch (e) {
console.log(e);
}
finally {
if (initLoading) {
setInitLoading(false);
}
}
};
const handleSearch = async () => {
setSearchLoading(true);
const bundles = await getBundle();
const products = await getProduct();
setAddNewData([...products, ...bundles]);
setSearchLoading(false);
};
const fetchMoreData = async () => {
setFetchMoreLoading(true);
try {
await getData();
}
catch (e) {
console.log(e);
}
finally {
setFetchMoreLoading(false);
}
};
function onSubmit() {
const checkedData = addNewData.filter((item) => item.checked);
handleSubmit === null || handleSubmit === void 0 ? void 0 : handleSubmit(checkedData);
onHideModal();
}
const handleScroll = () => {
const el = scrollRef.current;
if (!el || fetchMoreLoading)
return;
const isAtBottom = el.scrollTop + el.clientHeight >= el.scrollHeight;
if (isAtBottom) {
setCurrPage((pre) => pre + 1);
}
};
const handleUnCheckedItem = (item) => {
const clone = [...addNewData];
if (item.bundle_id) {
const index = clone.findIndex((addData) => addData.bundle_id === item.bundle_id);
clone[index].checked = false;
setAddNewData(clone);
}
else {
const index = clone.findIndex((addData) => addData.product_id === item.product_id);
clone[index].checked = false;
setAddNewData(clone);
}
};
useEffect(() => {
if (show) {
getData();
handleCountAll();
}
}, [show]);
useEffect(() => {
if (currPage !== 0 && show) {
fetchMoreData();
}
}, [currPage]);
useEffect(() => {
const timerId = setTimeout(() => {
handleSearch();
}, 200);
return () => clearTimeout(timerId);
}, [searchValue]);
return (React.createElement(React.Fragment, null,
React.createElement(PHXModal, { primaryLoading: submitLoading, title: 'C\u00E1c s\u1EA3n ph\u1EA9m \u0111\u00E3 ch\u1ECDn', show: showModalSelected, onHide: () => {
setShowModalSelected(false);
setShow(true);
}, onPrimaryClick: onSubmit, closeButton: true, size: 'large', hiddenSubmit: true },
React.createElement("div", { className: 'border rounded-lg mt-3 overflow-hidden' },
React.createElement("div", { onScroll: handleScroll, ref: scrollRef, className: ' max-h-[calc(100vh-400px)] overflow-y-auto shadow-[0rem_0.0825rem_0rem_#00000012] rounded-bl-lg rounded-br-lg bg-white ' },
React.createElement(ProductTable, { data: checkedList, isVerifyProjectCode: isVerifyProjectCode, handleCheckData: (item, index) => {
handleUnCheckedItem(item);
if (checkedList.length === 1) {
setCheckedList([]);
setShowModalSelected(false);
setShow(true);
}
else {
const clone = [...checkedList];
clone.splice(index, 1);
setCheckedList(clone);
}
} })))),
React.createElement(PHXModal, { closeButton: true, primaryLoading: submitLoading, primaryActionText: 'Th\u00EAm m\u1EDBi', title: 'Th\u00EAm s\u1EA3n ph\u1EA9m', onHide: onHideModal, show: show, size: 'large', inCard: false, onSubmit: onSubmit, disableCloseButton: submitLoading },
React.createElement("button", { onClick: onHideModal, type: 'button', className: 'grid top-4 right-4 grid-cols-1 absolute rounded-md p-0.5 text-gray-400 hover:bg-gray-200 hover:text-gray-600' },
React.createElement("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', fill: 'currentColor', "aria-hidden": 'true', "data-slot": 'icon', className: 'h-5 w-5' },
React.createElement("path", { fillRule: 'evenodd', d: 'M5.47 5.47a.75.75 0 0 1 1.06 0L12 10.94l5.47-5.47a.75.75 0 1 1 1.06 1.06L13.06 12l5.47 5.47a.75.75 0 1 1-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 0 1-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 0 1 0-1.06Z', clipRule: 'evenodd' }))),
React.createElement("div", { className: ' absolute bottom-4' },
React.createElement(PHXButton, { secondary: true, disabled: checkedList.length === 0, onClick: () => {
setShowModalSelected(true);
setShow(false);
}, className: 'text-xs font-normal' },
"Ch\u1ECDn ",
`${checkedList.length}`,
"/",
`${countAll}`)),
React.createElement(PHXBannerWithCard, { show: true, title: 'L\u01B0u \u00FD', type: 'warning', hideCloseButton: true, description: 'C\u00E1c s\u1EA3n ph\u1EA9m ch\u01B0a \u0111\u01B0\u1EE3c t\u1EA1o m\u00E3 c\u00F4ng tr\u00ECnh \u1EDF n\u0103m h\u1ECDc \u0111\u00E3 ch\u1ECDn s\u1EBD kh\u00F4ng \u0111\u01B0\u1EE3c th\u00EAm v\u00E0o \u0111\u1EE3t m\u1EDF b\u00E1n, vui l\u00F2ng li\u00EAn h\u1EC7 K\u1EBF to\u00E1n \u0111\u1EC3 th\u00EAm m\u00E3 c\u00F4ng tr\u00ECnh.' }),
React.createElement("div", { className: 'border rounded-lg mt-3' },
React.createElement("div", { className: ' py-2 px-3 border-b' },
React.createElement("div", { className: 'relative w-full' },
React.createElement("span", { className: 'absolute inset-y-0 left-0 flex items-center pl-3 text-gray-600' },
React.createElement(MagnifyingGlassIcon, { className: 'h-4 w-4' })),
React.createElement("input", { autoComplete: 'off', className: 'block w-full rounded-lg border-[0.5px] border-gray-500 px-3 py-1.5 pl-9 pr-3 text-xs font-normal shadow-sm focus:border-gray-500 focus:outline-none focus:outline-offset-1 focus:outline-indigo-500 focus:ring-transparent', onChange: (e) => {
if (currPage !== 0) {
setCurrPage(0);
}
setSearchValue(e.target.value);
}, placeholder: 'Nh\u1EADp t\u00EAn ho\u1EB7c m\u00E3 s\u1EA3n ph\u1EA9m', type: 'text' }))),
initLoading || searchLoading ? (React.createElement(PHXSkeleton, { type: 'table', className: 'h-[calc(100vh-400px)] overflow-hidden' })) : (React.createElement(React.Fragment, null, addNewData.length > 0 ? (React.createElement("div", { onScroll: handleScroll, ref: scrollRef, className: ' h-[calc(100vh-400px)] overflow-y-auto shadow-[0rem_0.0825rem_0rem_#00000012] rounded-bl-lg rounded-br-lg bg-white ' },
React.createElement(ProductTable, { data: addNewData, isVerifyProjectCode: isVerifyProjectCode,
// @ts-ignore
handleCheckData: (item, index) => handleCheckData(index) }))) : (React.createElement(PHXEmptyRecord, { className: 'h-[calc(100vh-400px)] pt-10' }))))))));
}
//# sourceMappingURL=StoreProduct.js.map