diff --git a/package.json b/package.json index fa1d789..7b22551 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "prettier": "prettier --config prettier.config.js --write \"src/**/*.{ts,tsx,css,scss}\" \"e2e/**/*.ts\"", "release": "lerna version --no-git-tag-version", "serve": "webpack serve --mode=development", - "start": "openmrs develop", + "start": "openmrs develop --backend https://uat.kenyahmis.org/ ", "test-e2e": "playwright test", "test": "cross-env TZ=UTC jest --config jest.config.js --verbose false --passWithNoTests", "test:watch": "cross-env TZ=UTC jest --watch --config jest.config.js", diff --git a/src/billing-form/billing-form.component.tsx b/src/billing-form/billing-form.component.tsx index dba2fc4..b178ae7 100644 --- a/src/billing-form/billing-form.component.tsx +++ b/src/billing-form/billing-form.component.tsx @@ -15,18 +15,9 @@ import { import styles from './billing-form.scss'; import { useTranslation } from 'react-i18next'; import { showSnackbar } from '@openmrs/esm-framework'; -import { useFetchSearchResults, processBillItems } from '../billing.resource'; // Corrected the import path +import { useFetchSearchResults, processBillItems } from '../billing.resource'; import { mutate } from 'swr'; -type BillItem = { - uuid: string; - Item: string; - Qnty: number; - Price: number; - Total: number; - category: string; -}; - type BillingFormProps = { patientUuid: string; closeWorkspace: () => void; @@ -34,74 +25,130 @@ type BillingFormProps = { const BillingForm: React.FC = ({ patientUuid, closeWorkspace }) => { const { t } = useTranslation(); - const [GrandTotal, setGrandTotal] = useState(0); - const [searchOptions, setSearchOptions] = useState([]); - const [BillItems, setBillItems] = useState([]); - const [searchVal, setSearchVal] = useState(''); - const [category, setCategory] = useState(''); - const numberRef = useRef(null); + const [grandTotal, setGrandTotal] = useState(0); + const [searchOptions, setSearchOptions] = useState([]); + const [billItems, setBillItems] = useState([]); + const [searchVal, setSearchVal] = useState(''); + const [category, setCategory] = useState(''); - const toggleSearch = (choiceSelected: string) => { - setSearchVal(''); - setSearchOptions([]); + const toggleSearch = (choiceSelected) => { + (document.getElementById('searchField') as HTMLInputElement).disabled = false; setCategory(choiceSelected === 'Stock Item' ? 'Stock Item' : 'Service'); }; - const calculateTotal = (event: React.ChangeEvent, itemName: string) => { - const Qnty = parseInt(event.target.value); - const price = BillItems.find((item) => item.Item.toLowerCase() === itemName.toLowerCase())?.Price || 0; - const total = price * Qnty; + const calculateTotal = (event, itemName) => { + const Qnty = event.target.value; + const price = document.getElementById(`${event.target.id}Price`).innerHTML; + const total = parseInt(price) * Qnty; - const updatedBillItems = BillItems.map((item) => - item.Item.toLowerCase() === itemName.toLowerCase() ? { ...item, Qnty, Total: total } : item, - ); + const updatedItems = billItems.map((item) => { + if (item.Item.toLowerCase().includes(itemName.toLowerCase())) { + item.Qnty = Qnty; + item.Total = total; + } + return item; + }); - setBillItems(updatedBillItems); + setBillItems(updatedItems); - const grandTotal = updatedBillItems.reduce((acc, curr) => acc + curr.Total, 0); - setGrandTotal(grandTotal); + const totals = Array.from(document.querySelectorAll('[id$="Total"]')); + let addUpTotals = 0; + totals.forEach((tot) => { + addUpTotals += parseInt(tot.innerHTML); + }); + setGrandTotal(addUpTotals); }; - const addItemToBill = (item: BillItem) => { - const existingItemIndex = BillItems.findIndex((existingItem) => existingItem.Item === item.Item); - - if (existingItemIndex !== -1) { - const updatedBillItems = [...BillItems]; - updatedBillItems[existingItemIndex].Qnty += 1; - updatedBillItems[existingItemIndex].Total = - updatedBillItems[existingItemIndex].Price * updatedBillItems[existingItemIndex].Qnty; - setBillItems(updatedBillItems); - } else { - setBillItems((prevItems) => [...prevItems, { ...item, Qnty: 1, Total: item.Price }]); - } + const calculateTotalAfterAddBillItem = () => { + const sum = billItems.reduce((acc, item) => acc + item.Price, 0); + setGrandTotal(sum); + }; + + const addItemToBill = (event, itemid, itemname, itemcategory, itemPrice) => { + const newItem = { + uuid: itemid, + Item: itemname, + Qnty: 1, + Price: itemPrice, + Total: itemPrice, + category: itemcategory, + }; - setGrandTotal((prevTotal) => prevTotal + item.Price); - setSearchVal(''); + setBillItems([...billItems, newItem]); setSearchOptions([]); + calculateTotalAfterAddBillItem(); + (document.getElementById('searchField') as HTMLInputElement).value = ''; + }; + + const { data, error, isLoading, isValidating } = useFetchSearchResults(searchVal, category); + + const filterItems = (val) => { + setSearchVal(val); + + if (!isLoading && data) { + const res = data as { results: any[] }; + + const options = res.results.map((o) => { + if (o.commonName && o.commonName !== '') { + return { + uuid: o.uuid || '', + Item: o.commonName, + Qnty: 1, + Price: 10, + Total: 10, + category: 'StockItem', + }; + } else if (o.name.toLowerCase().includes(val.toLowerCase())) { + return { + uuid: o.uuid || '', + Item: o.name, + Qnty: 1, + Price: o.servicePrices[0].price, + Total: o.servicePrices[0].price, + category: 'Service', + }; + } + }); + + setSearchOptions(options.filter((option) => option)); // Filter out undefined/null values + } }; const postBillItems = () => { const bill = { cashPoint: '54065383-b4d4-42d2-af4d-d250a1fd2590', cashier: 'f9badd80-ab76-11e2-9e96-0800200c9a66', - lineItems: BillItems.map((item) => ({ - [item.category === 'StockItem' ? 'item' : 'billableService']: item.uuid, - quantity: item.Qnty, + lineItems: [], + payments: [], + patient: patientUuid, + status: 'PENDING', + }; + + billItems.forEach((item) => { + const lineItem: any = { + quantity: parseInt(item.Qnty), price: item.Price, priceName: 'Default', priceUuid: '7b9171ac-d3c1-49b4-beff-c9902aee5245', lineItemOrder: 0, paymentStatus: 'PENDING', - })), - payments: [], - patient: patientUuid, - status: 'PENDING', - }; + }; + + if (item.category === 'StockItem') { + lineItem.item = item.uuid; + } else { + lineItem.billableService = item.uuid; + } + bill.lineItems.push(lineItem); + }); + + const url = `/ws/rest/v1/cashier/bill`; processBillItems(bill).then( () => { closeWorkspace(); + mutate((key) => typeof key === 'string' && key.startsWith(url), undefined, { revalidate: true }); showSnackbar({ title: t('billItems', 'Save Bill'), subtitle: 'Bill processing has been successful', @@ -122,31 +169,39 @@ const BillingForm: React.FC = ({ patientUuid, closeWorkspace } name="radio-button-group" defaultSelected="radio-1" className={styles.billingItem} - onChange={({ value }) => toggleSearch(value)}> + onChange={toggleSearch}> - setSearchVal(e.target.value)} - className={styles.billingItem} - /> - -
    - {searchOptions.map((row) => ( -
  • - -
  • - ))} -
+
+ {}} + className={styles.billingItem} + onKeyUp={(e) => { + filterItems(e.target.value); + }} + /> + +
    + {searchOptions.map((row) => ( +
  • + +
  • + ))} +
+
@@ -158,28 +213,38 @@ const BillingForm: React.FC = ({ patientUuid, closeWorkspace } - {BillItems.map((row) => ( - - {row.Item} - - calculateTotal(e, row.Item)} - /> - - {row.Price} - {row.Total} - - ))} + {billItems && Array.isArray(billItems) ? ( + billItems.map((row) => ( + + {row.Item} + + { + calculateTotal(e, row.Item); + row.Qnty = e.target.value; + }} + /> + + {row.Price} + + {row.Total} + + + )) + ) : ( +

Loading...

+ )} - - + + Grand Total: - {GrandTotal} + {grandTotal}