Skip to content

Commit

Permalink
Merge branch 'main' into O3-2910
Browse files Browse the repository at this point in the history
  • Loading branch information
CynthiaKamau authored Mar 28, 2024
2 parents e6908b0 + 37f8d6d commit d03876c
Show file tree
Hide file tree
Showing 15 changed files with 2,667 additions and 2,476 deletions.
672 changes: 336 additions & 336 deletions .yarn/releases/yarn-4.0.2.cjs → .yarn/releases/yarn-4.1.1.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ plugins:
- path: .yarn/plugins/@yarnpkg/plugin-outdated.cjs
spec: "https://mskelton.dev/yarn-outdated/v3"

yarnPath: .yarn/releases/yarn-4.0.2.cjs
yarnPath: .yarn/releases/yarn-4.1.1.cjs
15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,16 @@
"zod": "^3.22.4"
},
"peerDependencies": {
"@openmrs/esm-framework": "*",
"@openmrs/esm-patient-common-lib": "6.x",
"@openmrs/esm-framework": "5.x",
"@openmrs/esm-patient-common-lib": "7.x",
"react": "18.x",
"react-dom": "18.x",
"react-i18next": "11.x",
"rxjs": "6.x"
"rxjs": "6.x",
"swr": "2.x"
},
"devDependencies": {
"@openmrs/esm-framework": "next",
"@openmrs/esm-framework": "^5.5.1-pre.1659",
"@openmrs/esm-patient-common-lib": "next",
"@playwright/test": "^1.41.1",
"@swc/cli": "^0.3.2",
Expand Down Expand Up @@ -98,7 +99,7 @@
"jest-environment-jsdom": "^29.7.0",
"lerna": "^8.0.2",
"lodash": "^4.17.21",
"openmrs": "next",
"openmrs": "^5.5.1-pre.1659",
"pinst": "^3.0.0",
"prettier": "^3.2.4",
"pretty-quick": "^4.0.0",
Expand All @@ -110,13 +111,13 @@
"sass": "^1.70.0",
"swc-loader": "^0.2.3",
"swr": "^2.2.4",
"turbo": "^1.11.3",
"turbo": "^1.13.0",
"typescript": "^4.9.5",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": "eslint --cache --fix"
},
"packageManager": "yarn@4.0.2"
"packageManager": "yarn@4.1.1"
}
15 changes: 3 additions & 12 deletions src/bill-history/bill-history.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,7 @@ import {
Tile,
} from '@carbon/react';
import { isDesktop, useConfig, useLayoutType, usePagination } from '@openmrs/esm-framework';
import {
CardHeader,
EmptyDataIllustration,
ErrorState,
launchPatientWorkspace,
usePaginationInfo,
} from '@openmrs/esm-patient-common-lib';
import { CardHeader, EmptyDataIllustration, ErrorState, launchPatientWorkspace } from '@openmrs/esm-patient-common-lib';
import { useBills } from '../billing.resource';
import InvoiceTable from '../invoice/invoice-table.component';
import styles from './bill-history.scss';
Expand Down Expand Up @@ -101,7 +95,7 @@ const BillHistory: React.FC<BillHistoryProps> = ({ patientUuid }) => {
<EmptyDataIllustration />
</div>
<p className={styles.content}>There are no bills to display.</p>
<Button onClick={() => launchPatientWorkspace('billing-form')} kind="ghost">
<Button onClick={() => launchPatientWorkspace('billing-form-workspace')} kind="ghost">
{t('launchBillForm', 'Launch bill form')}
</Button>
</Tile>
Expand All @@ -112,10 +106,7 @@ const BillHistory: React.FC<BillHistoryProps> = ({ patientUuid }) => {
return (
<>
<CardHeader title={t('billingHistory', 'Billing History')}>
<Button
renderIcon={Add}
onClick={() => launchPatientWorkspace('billing-form', { workspaceTitle: 'Billing Form' })}
kind="ghost">
<Button renderIcon={Add} onClick={() => launchPatientWorkspace('billing-form-workspace', {})} kind="ghost">
{t('addBill', 'Add bill item(s)')}
</Button>
</CardHeader>
Expand Down
229 changes: 123 additions & 106 deletions src/billing-form/billing-form.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import React, { useState, useEffect, useMemo } from 'react';
import {
ButtonSet,
Button,
Form,
InlineLoading,
RadioButtonGroup,
RadioButton,
Search,
Stack,
Table,
TableHead,
TableBody,
Expand All @@ -14,7 +17,7 @@ import {
} from '@carbon/react';
import styles from './billing-form.scss';
import { useTranslation } from 'react-i18next';
import { restBaseUrl, showSnackbar, showToast, useConfig, useDebounce } from '@openmrs/esm-framework';
import { restBaseUrl, showSnackbar, showToast, useConfig, useDebounce, useLayoutType } from '@openmrs/esm-framework';
import { useFetchSearchResults, processBillItems } from '../billing.resource';
import { mutate } from 'swr';
import { convertToCurrency } from '../helpers';
Expand All @@ -32,13 +35,15 @@ type BillingFormProps = {
const BillingForm: React.FC<BillingFormProps> = ({ patientUuid, closeWorkspace }) => {
const { t } = useTranslation();
const { defaultCurrency } = useConfig();
const isTablet = useLayoutType() === 'tablet';

const [grandTotal, setGrandTotal] = useState(0);
const [searchOptions, setSearchOptions] = useState([]);
const [billItems, setBillItems] = useState([]);
const [searchVal, setSearchVal] = useState('');
const [category, setCategory] = useState('');
const [saveDisabled, setSaveDisabled] = useState<boolean>(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [addedItems, setAddedItems] = useState([]);
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm);
Expand Down Expand Up @@ -157,6 +162,7 @@ const BillingForm: React.FC<BillingFormProps> = ({ patientUuid, closeWorkspace }
}, [filterItems]);

const postBillItems = () => {
setIsSubmitting(true);
const bill = {
cashPoint: '54065383-b4d4-42d2-af4d-d250a1fd2590',
cashier: 'f9badd80-ab76-11e2-9e96-0800200c9a66',
Expand Down Expand Up @@ -187,7 +193,9 @@ const BillingForm: React.FC<BillingFormProps> = ({ patientUuid, closeWorkspace }

const url = `${apiBasePath}bill`;
processBillItems(bill).then(
(res) => {
() => {
setIsSubmitting(false);

closeWorkspace();
mutate((key) => typeof key === 'string' && key.startsWith(url), undefined, { revalidate: true });
showSnackbar({
Expand All @@ -198,118 +206,127 @@ const BillingForm: React.FC<BillingFormProps> = ({ patientUuid, closeWorkspace }
});
},
(error) => {
setIsSubmitting(false);
showSnackbar({ title: 'Bill processing error', kind: 'error', subtitle: error?.message });
},
);
};

return (
<div className={styles.billingFormContainer}>
<RadioButtonGroup
legendText={t('selectCategory', 'Select category')}
name="radio-button-group"
defaultSelected="radio-1"
className={styles.billingItem}
onChange={toggleSearch}>
<RadioButton labelText={t('stockItem', 'Stock Item')} value="Stock Item" id="stockItem" />
<RadioButton labelText={t('service', 'Service')} value="Service" id="service" />
</RadioButtonGroup>

<div>
<Search
size="lg"
id="searchField"
disabled
closeButtonLabelText={t('clearSearchInput', 'Clear search input')}
className={styles.billingItem}
placeholder={t('searchItems', 'Search items and services')}
labelText={t('searchItems', 'Search items and services')}
onKeyUp={handleSearchTermChange}
/>

<ul className={styles.searchContent}>
{searchOptions?.length > 0 &&
searchOptions?.map((row) => (
<li key={row.uuid} className={styles.searchItem}>
<Button
id={row.uuid}
onClick={(e) => addItemToBill(e, row.uuid, row.Item, row.category, row.Price)}
style={{ background: 'inherit', color: 'black' }}>
{row.Item} Qnty.{row.Qnty} Ksh.{row.Price}
</Button>
</li>
))}

{searchOptions?.length === 0 && !isLoading && !!debouncedSearchTerm && (
<p>{t('noResultsFound', 'No results found')}</p>
)}
</ul>
</div>

<Table aria-label="sample table" className={styles.billingItem}>
<TableHead>
<TableRow>
<TableHeader>Item</TableHeader>
<TableHeader>Quantity</TableHeader>
<TableHeader>Price</TableHeader>
<TableHeader>Total</TableHeader>
<TableHeader>Action</TableHeader>
</TableRow>
</TableHead>
<TableBody>
{billItems && Array.isArray(billItems) ? (
billItems.map((row) => (
<Form className={styles.form}>
<div className={styles.grid}>
<Stack>
<RadioButtonGroup
legendText={t('selectCategory', 'Select category')}
name="radio-button-group"
defaultSelected="radio-1"
className={styles.mt2}
onChange={toggleSearch}>
<RadioButton labelText={t('stockItem', 'Stock Item')} value="Stock Item" id="stockItem" />
<RadioButton labelText={t('service', 'Service')} value="Service" id="service" />
</RadioButtonGroup>
</Stack>
<Stack>
<Search
size="lg"
id="searchField"
disabled
closeButtonLabelText={t('clearSearchInput', 'Clear search input')}
className={styles.mt2}
placeholder={t('searchItems', 'Search items and services')}
labelText={t('searchItems', 'Search items and services')}
onKeyUp={handleSearchTermChange}
/>
</Stack>
<Stack>
<ul className={styles.searchContent}>
{searchOptions?.length > 0 &&
searchOptions?.map((row) => (
<li key={row.uuid} className={styles.searchItem}>
<Button
id={row.uuid}
onClick={(e) => addItemToBill(e, row.uuid, row.Item, row.category, row.Price)}
style={{ background: 'inherit', color: 'black' }}>
{row.Item} Qnty.{row.Qnty} Ksh.{row.Price}
</Button>
</li>
))}

{searchOptions?.length === 0 && !isLoading && !!debouncedSearchTerm && (
<p>{t('noResultsFound', 'No results found')}</p>
)}
</ul>
</Stack>
<Stack>
<Table aria-label="sample table" className={styles.mt2}>
<TableHead>
<TableRow>
<TableCell>{row.Item}</TableCell>
<TableCell>
<input
type="number"
className={`form-control ${row.Qnty <= 0 ? styles.invalidInput : ''}`}
id={row.Item}
min={0}
max={100}
value={row.Qnty}
onChange={(e) => {
calculateTotal(e, row.Item);
row.Qnty = e.target.value;
}}
/>
</TableCell>
<TableCell id={row.Item + 'Price'}>{row.Price}</TableCell>
<TableCell id={row.Item + 'Total'} className="totalValue">
{row.Total}
</TableCell>
<TableCell>
<TrashCan onClick={() => removeItemFromBill(row.uuid)} className={styles.removeButton} />
</TableCell>
<TableHeader>Item</TableHeader>
<TableHeader>Quantity</TableHeader>
<TableHeader>Price</TableHeader>
<TableHeader>Total</TableHeader>
<TableHeader>Action</TableHeader>
</TableRow>
))
) : (
<p>Loading...</p>
)}
<TableRow>
<TableCell></TableCell>
<TableCell></TableCell>
<TableCell style={{ fontWeight: 'bold' }}>Grand Total:</TableCell>
<TableCell id="GrandTotalSum">{convertToCurrency(grandTotal, defaultCurrency)}</TableCell>
</TableRow>
</TableBody>
</Table>

<ButtonSet className={styles.billingItem}>
<Button kind="secondary" onClick={closeWorkspace}>
{t('discard', 'Discard')}
</Button>
<Button
kind="primary"
disabled={saveDisabled}
onClick={() => {
postBillItems();
}}>
{t('save', 'Save')}
</Button>
</ButtonSet>
</div>
</TableHead>
<TableBody>
{billItems && Array.isArray(billItems) ? (
billItems.map((row) => (
<TableRow>
<TableCell>{row.Item}</TableCell>
<TableCell>
<input
type="number"
className={`form-control ${row.Qnty <= 0 ? styles.invalidInput : ''}`}
id={row.Item}
min={0}
max={100}
value={row.Qnty}
onChange={(e) => {
calculateTotal(e, row.Item);
row.Qnty = e.target.value;
}}
/>
</TableCell>
<TableCell id={row.Item + 'Price'}>{row.Price}</TableCell>
<TableCell id={row.Item + 'Total'} className="totalValue">
{row.Total}
</TableCell>
<TableCell>
<TrashCan onClick={() => removeItemFromBill(row.uuid)} className={styles.removeButton} />
</TableCell>
</TableRow>
))
) : (
<p>Loading...</p>
)}
<TableRow>
<TableCell colSpan={3}></TableCell>
<TableCell style={{ fontWeight: 'bold' }}>{t('grandTotal', 'Grand total')}:</TableCell>
<TableCell id="GrandTotalSum">{convertToCurrency(grandTotal, defaultCurrency)}</TableCell>
</TableRow>
</TableBody>
</Table>
</Stack>

<ButtonSet className={isTablet ? styles.tablet : styles.desktop}>
<Button className={styles.button} kind="secondary" disabled={isSubmitting} onClick={closeWorkspace}>
{t('discard', 'Discard')}
</Button>
<Button
className={styles.button}
kind="primary"
onClick={postBillItems}
disabled={isSubmitting && saveDisabled}
type="submit">
{isSubmitting ? (
<InlineLoading description={t('saving', 'Saving') + '...'} />
) : (
t('saveAndClose', 'Save and close')
)}
</Button>
</ButtonSet>
</div>
</Form>
);
};

Expand Down
Loading

0 comments on commit d03876c

Please sign in to comment.