Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

O3-4283 - feat/Print item transactions (Bin Card and Stock Card) - BIN CARD #246

Merged
merged 4 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"lodash-es": "^4.17.21",
"react-hook-form": "^7.45.4",
"react-image-annotate": "^1.8.0",
"react-to-print": "^2.14.13",
"yup": "^1.2.0",
"zod": "^3.22.2"
},
Expand Down
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import StockSources from './stock-sources/stock-sources.component';
import StockLocations from './stock-locations/stock-locations.component';
import StockReports from './stock-reports/report-list/stock-reports.component';
import StockSettings from './stock-settings/stock-settings.component';
import TransactionsPrintPreview from './stock-items/add-stock-item/transactions/printout/transactions-print-preview.modal';
const moduleName = '@openmrs/esm-stock-management-app';

const options = {
Expand Down Expand Up @@ -126,7 +127,7 @@ export const deletePackagingUnitButton = getSyncLifecycle(deletePackagingUnitMod
});

export const stockManagementAppMenuItem = getSyncLifecycle(appMenu, options);

export const transactionPrintPreviewModal = getSyncLifecycle(TransactionsPrintPreview, options)
export function startupApp() {
defineConfigSchema(moduleName, configSchema);
}
6 changes: 5 additions & 1 deletion src/routes.json
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@
{
"name": "stock-operation-dialog",
"component": "stockOperationModal"
},
{
"name": "transactions-print-preview-modal",
"component": "transactionPrintPreviewModal"
}
],
"pages": [
Expand All @@ -206,4 +210,4 @@
"route": "stock-management"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import styles from './printable-transaction-footer.scss';
import { useTranslation } from 'react-i18next';
import dayjs from 'dayjs';
import { formatDate, useSession } from '@openmrs/esm-framework';

type PrintableFooterProps = {
title: string;
};

const PrintableTransactionFooter: React.FC<PrintableFooterProps> = ({ title }) => {
const { t } = useTranslation();
const session = useSession();

return (
<div className={styles.container}>
<p className={styles.itemFooter}>{title}</p>
<p className={styles.footDescription}>
{t(
'generatedMessage',
'The card has been electronically generated and is a valid document. It was created by {{userName}} on {{date}}',
{
userName: `${session?.user?.display}`,
// date: dayjs().format('DD-MM-YYYY'),
// time: dayjs().format('hh:mm A'),
date: `${formatDate(new Date(), { mode: 'standard', noToday: true })}`,
},
)}
</p>
</div>
);
};

export default PrintableTransactionFooter;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@use '@carbon/colors';
@use '@carbon/layout';
@use '@carbon/type';

.container {
display: flex;
flex-direction: column;
width: 100%;
bottom: 0;
padding: layout.$spacing-01;
justify-content: center;
}

.itemFooter {
padding: layout.$spacing-01 layout.$spacing-05;
@include type.type-style('body-compact-02');
color: colors.$cool-gray-90;
}

.footDescription {
@include type.type-style('legal-01');
padding: layout.$spacing-01 layout.$spacing-05;
color: colors.$cool-gray-70;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from 'react';
import styles from './printable-transaction-header.scss';
import { useConfig } from '@openmrs/esm-framework';
import { useTranslation } from 'react-i18next';
import startCase from 'lodash-es/startCase';

interface PrintableTransactionHeaderProps {
itemName: string;
}

const PrintableTransactionHeader: React.FC<PrintableTransactionHeaderProps> = ({ itemName }) => {
const { t } = useTranslation();
const { logo } = useConfig({ externalModuleName: '@kenyaemr/esm-login-app' });

return (
<div className={styles.container}>
<div className={styles.printableHeader}>
<p className={styles.heading}>{t('bincard', 'Bin Card')}</p>
{logo?.src ? (
<img className={styles.img} height={60} width={250} src={logo.src} alt={logo.alt} />
) : logo?.name ? (
logo.name
) : (
// OpenMRS Logo
PatrickWaweru marked this conversation as resolved.
Show resolved Hide resolved
<svg
className={styles.img}
role="img"
width={110}
height={40}
viewBox="0 0 380 119"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M40.29 40.328a27.755 27.755 0 0 1 19.688-8.154c7.669 0 14.613 3.102 19.647 8.116l.02-18.54A42.835 42.835 0 0 0 59.978 17c-7.089 0-13.813 1.93-19.709 4.968l.021 18.36ZM79.645 79.671a27.744 27.744 0 0 1-19.684 8.154c-7.67 0-14.614-3.101-19.651-8.116l-.02 18.54A42.857 42.857 0 0 0 59.96 103a42.833 42.833 0 0 0 19.672-4.751l.013-18.578ZM40.328 79.696c-5.038-5.037-8.154-11.995-8.154-19.685 0-7.669 3.102-14.612 8.116-19.65l-18.54-.02A42.85 42.85 0 0 0 17 60.012a42.819 42.819 0 0 0 4.752 19.672l18.576.013ZM79.634 40.289a27.753 27.753 0 0 1 8.154 19.688 27.744 27.744 0 0 1-8.117 19.646l18.542.02a42.842 42.842 0 0 0 4.749-19.666c0-7.09-1.714-13.779-4.751-19.675l-18.577-.013ZM156.184 60.002c0-8.748-6.118-15.776-15.025-15.776-8.909 0-15.025 7.028-15.025 15.776 0 8.749 6.116 15.78 15.025 15.78 8.907 0 15.025-7.031 15.025-15.78Zm-34.881 0c0-11.482 8.318-19.958 19.856-19.958 11.536 0 19.855 8.477 19.855 19.959 0 11.484-8.319 19.964-19.855 19.964-11.538 0-19.856-8.48-19.856-19.965ZM179.514 75.54c5.507 0 9.05-4.14 9.05-9.482 0-5.341-3.543-9.483-9.05-9.483-5.505 0-9.046 4.142-9.046 9.483 0 5.342 3.541 9.482 9.046 9.482ZM166.22 53.306h4.248v3.704h.11c2.344-2.725 5.449-4.36 9.154-4.36 8.014 0 13.408 5.67 13.408 13.408 0 7.63-5.613 13.406-12.752 13.406-4.58 0-8.231-2.29-9.81-5.178h-.11V90.87h-4.248V53.306ZM217.773 63.768c-.163-4.305-3-7.193-7.686-7.193-4.685 0-7.79 2.888-8.335 7.193h16.021Zm3.653 10.412c-3.001 3.868-6.596 5.284-11.339 5.284-8.01 0-12.914-5.993-12.914-13.406 0-7.901 5.559-13.407 13.08-13.407 7.196 0 12.096 4.906 12.096 13.354v1.362h-20.597c.325 4.413 3.704 8.173 8.335 8.173 3.65 0 6.105-1.307 8.12-3.868l3.219 2.508ZM227.854 59.356c0-2.346-.216-4.36-.216-6.05h4.031c0 1.363.11 2.777.11 4.195h.11c1.144-2.505 4.306-4.85 8.5-4.85 6.705 0 9.699 4.252 9.699 10.41v15.748h-4.248v-15.31c0-4.253-1.856-6.924-5.833-6.924-5.503 0-7.903 3.979-7.903 9.811V78.81h-4.25V59.356ZM259.211 41.008h6.708L278.8 70.791h.107l12.982-29.782h6.549v37.99h-4.506V47.124h-.106L280.192 79h-2.738l-13.629-31.875h-.107V79h-4.507V41.01ZM312.392 57.752h4.023c4.992 0 11.487 0 11.487-6.282 0-5.47-4.776-6.276-9.177-6.276h-6.333v12.558Zm-4.506-16.744h9.711c7.352 0 15.132 1.072 15.132 10.462 0 5.527-3.594 9.125-9.495 10.037L334.018 79h-5.525l-10.304-17.063h-5.797V79h-4.506V41.01ZM358.123 47.712c-1.506-2.413-4.187-3.486-6.926-3.486-3.973 0-8.1 1.88-8.1 6.385 0 3.49 1.931 5.047 7.994 6.98 5.903 1.878 11.377 3.809 11.377 11.267 0 7.567-6.495 11.11-13.36 11.11-4.402 0-9.125-1.45-11.7-5.262l3.862-3.165c1.61 2.794 4.83 4.24 8.105 4.24 3.862 0 8.263-2.253 8.263-6.601 0-4.669-3.165-5.474-9.928-7.728-5.366-1.771-9.442-4.134-9.442-10.463 0-7.298 6.277-10.945 12.929-10.945 4.241 0 7.836 1.178 10.625 4.45l-3.699 3.218Z"
/>
</svg>
)}
</div>

<div className={styles.printableBody}>
<div className={styles.transactionDetails}>
<p className={styles.itemHeading}>{t('itemname', 'Item Name')}</p>
<p className={styles.itemLabel}>{startCase(itemName)}</p>
</div>
</div>
</div>
);
};

export default PrintableTransactionHeader;
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
@use '@carbon/colors';
@use '@carbon/layout';
@use '@carbon/type';

.container {
padding: 0 1rem 2rem;
border-bottom: 1px solid #ebedf2;
margin-bottom: 2rem;
}

.printableBody {
display: flex;
flex-direction: row;
justify-content: space-between;
}

.printableHeader {
display: flex;
flex-direction: row;
}

.img {
display: flex;
margin-left: auto;
}

.transactionDetails {
display: flex;
width: 50%;
flex-direction: column;
}

.facilityDetails {
display: flex;
flex-flow: column wrap;
text-align: right;
}

.heading {
font-size: 40px;
text-transform: uppercase;
margin-bottom: layout.$spacing-05;
}

.facilityName {
@include type.type-style('heading-compact-02');
font-weight: bold;
color: colors.$green-70;
}

.itemHeading {
@include type.type-style('body-compact-02');
margin-bottom: 0.25rem;
font-weight: bold;
color: colors.$cool-gray-90;
}

.itemLabel {
@include type.type-style('body-compact-02');
color: colors.$cool-gray-90;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
@use '@carbon/colors';
@use '@carbon/layout';
@use '@carbon/type';

.printableInvoiceContainer {
display: flex;
flex-direction: row;
}

.container {
margin-top: layout.$spacing-05;
}

.itemsContainer {
display: flex;
flex-direction: column;
width: 96%;
padding: layout.$spacing-05;
margin: layout.$spacing-05;
font-size: 6px;
}

.detailsContainer {
margin: layout.$spacing-05 0;
width: 20%;
}

.tableContainer {
margin-bottom: layout.$spacing-05;
font-size: 6px;
}

.totalContainer {
display: flex;
flex-direction: column;
}

.item {
margin: layout.$spacing-04;
}

.itemHeading {
@include type.type-style('label-02');
font-style: bold;
color: colors.$cool-gray-90;
margin-bottom: layout.$spacing-01;
}

.itemValue {
@include type.type-style('legal-01');
color: colors.$cool-gray-90;
}

.itemTotal {
border-bottom: solid 0.00125rem colors.$cool-gray-10;
padding: layout.$spacing-02;
}

.itemLabel {
float: right;
@include type.type-style('label-01');
}

.tableBody {
font-size: 8px;
}

.printButton {
padding: layout.$spacing-01;
margin: layout.$spacing-01;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import { Button, Stack, ComboButton, MenuItem } from '@carbon/react';
import { Printer } from '@carbon/react/icons';
import { useTranslation } from 'react-i18next';
import { useStockItem } from '../../../stock-items.resource';
import { showModal } from '@openmrs/esm-framework';
import styles from './printable-transaction.scss';

type Props = {
itemUuid: string;
columns: any;
data: any;
};

const TransactionsPrintAction: React.FC<Props> = ({ columns, data, itemUuid }) => {
const { t } = useTranslation();

const { item: stockItem, isLoading: isStockItemLoading } = useStockItem(itemUuid);

const handleClick = () => {
// stockItem.drugName || stockItem.conceptName || ''
const dispose = showModal('transactions-print-preview-modal', {
onClose: () => dispose(),
title: stockItem.drugName || stockItem.conceptName || '',
columns,
data,
});
};

return (
<>
<ComboButton label="Print">
<MenuItem
label={t('printStockCard', 'Print Stock Card')}
renderIcon={(props) => <Printer size={24} {...props} />}
iconDescription="Print Stock Card"
/>
<MenuItem
label={t('printBinCard', 'Print Bin Card')}
renderIcon={(props) => <Printer size={24} {...props} />}
iconDescription="Print Bin Card"
onClick={handleClick}
disabled={isStockItemLoading}
/>
</ComboButton>
</>
);
};

export default TransactionsPrintAction;
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { useRef } from 'react';
import TransactionsPrintout from './transactions-printout.component';
import { ModalBody, ModalHeader, ModalFooter, Button } from '@carbon/react';
import { useTranslation } from 'react-i18next';
import { useReactToPrint } from 'react-to-print';
type Props = {
onClose?: () => void;
title?: string;
columns: any;
data: any;
};

const TransactionsPrintPreview: React.FC<Props> = ({ onClose, title, columns, data }) => {
const { t } = useTranslation();
const ref = useRef<HTMLDivElement>(null);

const handlePrint = useReactToPrint({
content: () => ref.current,
});
return (
<>
<ModalHeader closeModal={onClose} title={t('printbincard', 'Print Bin Card')} />
<ModalBody>
<div ref={ref}>
<TransactionsPrintout title={title} columns={columns} data={data} />
</div>
</ModalBody>
<ModalFooter>
<Button kind="secondary" onClick={onClose}>
{t('cancel', 'Cancel')}
</Button>
<Button type="button" onClick={handlePrint}>
{t('print', 'Print')}
</Button>
</ModalFooter>
</>
);
};

export default TransactionsPrintPreview;
Loading
Loading