Skip to content

Commit

Permalink
(fix) Add the payment mode module
Browse files Browse the repository at this point in the history
  • Loading branch information
Munyua123 committed Dec 17, 2024
1 parent a23f0c0 commit d67783a
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 153 deletions.
5 changes: 4 additions & 1 deletion packages/esm-billing-app/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ import VisitAttributeTags from './invoice/payments/visit-tags/visit-attribute.co
import ServiceMetrics from './billable-services/dashboard/service-metrics.component';
import appMenu from './billable-services/billable-services-menu-item/item.component';

import DrugOrder from './billable-services/billable-item/drug-order/drug-order.component';
// import DrugOrder from './billable-services/billable-item/drug-order/drug-order.component';
import LabOrder from './billable-services/billable-item/test-order/lab-order.component';
import ProcedureOrder from './billable-services/billable-item/test-order/procedure-order.component';
import PriceInfoOrder from './billable-services/billable-item/test-order/price-info-order.componet';

import { BulkImportBillableServices } from './billable-services/bulk-import-billable-service.modal';

import { CreatePaymentPoint } from './payment-points/create-payment-point.component';
import CreatePaymentMode from './payment-modes/payment-mode.workspace';

import { ClockIn } from './payment-points/payment-point/clock-in.component';
import { ClockOut } from './payment-points/payment-point/clock-out.component';
import DeletePaymentModeModal from './payment-modes/delete-payment-mode.modal';
Expand Down Expand Up @@ -104,6 +106,7 @@ export const visitAttributeTags = getSyncLifecycle(VisitAttributeTags, options);
export const billableServicesAppMenuItem = getSyncLifecycle(appMenu, options);

export const createPaymentPoint = getSyncLifecycle(CreatePaymentPoint, options);
export const createPaymentMode = getSyncLifecycle(CreatePaymentMode, options)

// export const drugOrder = getSyncLifecycle(DrugOrder, options);
export const labOrder = getSyncLifecycle(LabOrder, options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ const PaymentModeDashboard: React.FC<PaymentModeDashboardProps> = () => {
});
};

const createPaymentModeModal = () => {
const dispose = showModal('create-payment-mode', {
closeModal: () => dispose(),
});
}

if (isLoading) {
return <DataTableSkeleton />;
}
Expand Down Expand Up @@ -106,13 +112,7 @@ const PaymentModeDashboard: React.FC<PaymentModeDashboardProps> = () => {
<div>
<CardHeader title="Payment Modes">
<Button
onClick={() => {
console.log('Add Payment Mode button clicked');
launchWorkspace('payment-mode-workspace', { workspaceTitle: 'Add Payment Mode' });
console.log('launchWorkspace triggered with:', 'payment-mode-workspace', {
workspaceTitle: 'Add Payment Mode',
})
}}
onClick={() => {createPaymentModeModal()}}
className={styles.addPaymentModeButton}
size="md"
kind="ghost">
Expand Down
228 changes: 83 additions & 145 deletions packages/esm-billing-app/src/payment-modes/payment-mode.workspace.tsx
Original file line number Diff line number Diff line change
@@ -1,89 +1,68 @@
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import {
DefaultWorkspaceProps,
ResponsiveWrapper,
restBaseUrl,
showSnackbar,
useLayoutType,
} from '@openmrs/esm-framework';
import { Controller, FormProvider, useFieldArray, useForm } from 'react-hook-form';
import { Button, Form, Loading, ModalBody, ModalFooter, ModalHeader, TextInput } from '@carbon/react';
import { restBaseUrl, showSnackbar, useLayoutType } from '@openmrs/esm-framework';
import { Controller, useForm } from 'react-hook-form';
import styles from './payment-mode.workspace.scss';
import { TextInput, ButtonSet, Button, InlineLoading, Stack, Toggle } from '@carbon/react';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
import classNames from 'classnames';
import { createPaymentMode, handleMutation } from './payment-mode.resource';
import { PaymentMode } from '../types';
import usePaymentModeFormSchema from './usePaymentModeFormSchema';
import PaymentModeAttributeFields from './payment-attributes/payment-mode-attributes.component';
import { Add } from '@carbon/react/icons';

type PaymentModeWorkspaceProps = DefaultWorkspaceProps & {
initialPaymentMode?: PaymentMode;
};

const PaymentModeWorkspace: React.FC<PaymentModeWorkspaceProps> = ({
closeWorkspace,
promptBeforeClosing,
closeWorkspaceWithSavedChanges,
initialPaymentMode = {} as PaymentMode,
}) => {
const CreatePaymentMode = ({ closeModal }) => {
const { t } = useTranslation();
const isTablet = useLayoutType() === 'tablet';
const { paymentModeFormSchema } = usePaymentModeFormSchema();
type PaymentModeFormSchema = z.infer<typeof paymentModeFormSchema>;
const formDefaultValues = Object.keys(initialPaymentMode).length > 0 ? initialPaymentMode : {};

const formMethods = useForm<PaymentModeFormSchema>({
resolver: zodResolver(paymentModeFormSchema),
mode: 'all',
defaultValues: formDefaultValues,
});

const { errors, isSubmitting, isDirty } = formMethods.formState;
const { errors, isSubmitting } = formMethods.formState;

// field array
const {
fields: attributeTypeFields,
append: appendAttributeType,
remove: removeAttributeType,
} = useFieldArray({
control: formMethods.control,
name: 'attributeTypes',
});
// const {
// fields: attributeTypeFields,
// append: appendAttributeType,
// remove: removeAttributeType,
// } = useFieldArray({
// control: formMethods.control,
// name: 'attributeTypes',
// });

const mappedAttributeTypes = (attributes) => {
return {
name: attributes.name,
description: attributes.description,
retired: attributes.retired,
attributeOrder: attributes?.attributeOrder ?? 0,
format: attributes?.format ?? '',
foreignKey: attributes?.foreignKey ?? null,
regExp: attributes?.regExp ?? '',
required: attributes.required,
};
};
// const mappedAttributeTypes = (attributes) => {
// return {
// name: attributes.name,
// description: attributes.description,
// retired: attributes.retired,
// attributeOrder: attributes?.attributeOrder ?? 0,
// format: attributes?.format ?? '',
// foreignKey: attributes?.foreignKey ?? null,
// regExp: attributes?.regExp ?? '',
// required: attributes.required,
// };
// };

const onSubmit = async (data: PaymentModeFormSchema) => {
const payload: Partial<PaymentMode> = {
name: data.name,
description: data.description,
retired: data.retired,
attributeTypes: data.attributeTypes.map(mappedAttributeTypes),
};

try {
const response = await createPaymentMode(payload, initialPaymentMode?.uuid ?? '');
const response = await createPaymentMode(payload, '');
if (response.ok) {
showSnackbar({
title: t('paymentModeCreated', 'Payment mode created successfully'),
subtitle: t('paymentModeCreatedSubtitle', 'The payment mode has been created successfully'),
kind: 'success',
isLowContrast: true,
});
closeWorkspaceWithSavedChanges();
closeModal()
handleMutation(`${restBaseUrl}/billing/paymentMode?v=full`);
}
} catch (error) {
Expand Down Expand Up @@ -115,104 +94,63 @@ const PaymentModeWorkspace: React.FC<PaymentModeWorkspaceProps> = ({
});
};

useEffect(() => {
if (isDirty) {
promptBeforeClosing(() => isDirty);
}
}, [isDirty, promptBeforeClosing]);

return (
<FormProvider {...formMethods}>
<form onSubmit={formMethods.handleSubmit(onSubmit, handleError)} className={styles.form}>
<div className={styles.formContainer}>
<Stack className={styles.formStackControl} gap={7}>
<ResponsiveWrapper>
<Controller
name="name"
control={formMethods.control}
render={({ field }) => (
<TextInput
{...field}
id="name"
type="text"
labelText={t('paymentModeName', 'Payment mode name')}
placeholder={t('paymentModeNamePlaceholder', 'Enter payment mode name')}
invalid={!!errors.name}
invalidText={errors.name?.message}
/>
)}
/>
</ResponsiveWrapper>
<ResponsiveWrapper>
<Controller
name="description"
control={formMethods.control}
render={({ field }) => (
<TextInput
{...field}
id="description"
type="text"
labelText={t('paymentModeDescription', 'Payment mode description')}
placeholder={t('paymentModeDescriptionPlaceholder', 'Enter payment mode description')}
invalid={!!errors.description}
invalidText={errors.description?.message}
/>
)}
/>
</ResponsiveWrapper>
<ResponsiveWrapper>
<Controller
name="retired"
control={formMethods.control}
render={({ field }) => (
<Toggle
{...field}
labelText={t('paymentModeRetired', 'Retired')}
labelA="Off"
labelB="On"
toggled={field.value}
id="retired"
onToggle={(value) => (value ? field.onChange(true) : field.onChange(false))}
/>
)}
/>
</ResponsiveWrapper>
<Button size="sm" kind="tertiary" renderIcon={Add} onClick={() => appendAttributeType({})}>
{t('addAttributeType', 'Add attribute type')}
</Button>
{attributeTypeFields.map((field, index) => (
<PaymentModeAttributeFields
key={field.id}
field={field}
index={index}
control={formMethods.control}
removeAttributeType={removeAttributeType}
errors={errors}
/>
))}
</Stack>
</div>
<ButtonSet className={classNames({ [styles.tablet]: isTablet, [styles.desktop]: !isTablet })}>
<Button style={{ maxWidth: '50%' }} kind="secondary" onClick={closeWorkspace}>
{t('cancel', 'Cancel')}
</Button>
<Button
disabled={isSubmitting || Object.keys(errors).length > 0}
style={{ maxWidth: '50%' }}
kind="primary"
type="submit">
{isSubmitting ? (
<span style={{ display: 'flex', justifyItems: 'center' }}>
{t('submitting', 'Submitting...')} <InlineLoading status="active" iconDescription="Loading" />
</span>
) : (
t('saveAndClose', 'Save & close')
)}
</Button>
</ButtonSet>
</form>
</FormProvider>
<Form>
<ModalHeader closeModal={closeModal}>Create Payment Mode</ModalHeader>
<ModalBody>
<Controller
name="name"
control={formMethods.control}
render={({ field }) => (
<TextInput
{...field}
id="name"
type="text"
labelText={t('paymentModeName', 'Payment mode name')}
placeholder={t('paymentModeNamePlaceholder', 'Enter payment mode name')}
invalid={!!errors.name}
invalidText={errors.name?.message}
/>
)}
/>
<Controller
name="description"
control={formMethods.control}
render={({ field }) => (
<TextInput
{...field}
id="description"
type="text"
labelText={t('paymentModeDescription', 'Payment mode description')}
placeholder={t('paymentModeDescriptionPlaceholder', 'Enter payment mode description')}
invalid={!!errors.description}
invalidText={errors.description?.message}
/>
)}
/>
</ModalBody>
<ModalFooter>
<Button style={{ maxWidth: '50%' }} kind="secondary" onClick={closeModal}>
{t('cancel', 'Cancel')}
</Button>
<Button
disabled={isSubmitting || Object.keys(errors).length > 0}
style={{ maxWidth: '50%' }}
kind="primary"
type="submit"
onClick={formMethods.handleSubmit(onSubmit, handleError)}>
{isSubmitting ? (
<>
<Loading className={styles.button_spinner} withOverlay={false} small />
{t('creating', 'Creating')}
</>
) : (
t('create', 'Create')
)}
</Button>
</ModalFooter>
</Form>
);
};

export default PaymentModeWorkspace;
export default CreatePaymentMode;
4 changes: 4 additions & 0 deletions packages/esm-billing-app/src/routes.json
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@
{
"name": "paid-bill-receipt-print-preview-modal",
"component": "paidBillReceiptPrintPreviewModal"
},
{
"name": "create-payment-mode",
"component": "createPaymentMode"
}
]
}

0 comments on commit d67783a

Please sign in to comment.