Skip to content

Commit

Permalink
Merge pull request #24 from openimis/feature/OM-119
Browse files Browse the repository at this point in the history
OM-119: add a voucher export functionality
  • Loading branch information
jdolkowski authored Feb 5, 2024
2 parents ad75357 + 12189c0 commit 213a5db
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 37 deletions.
16 changes: 16 additions & 0 deletions src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,19 @@ export function deleteVoucherPrice(voucherPriceUuid, clientMutationLabel) {
},
);
}

export function downloadWorkerVoucher(params) {
const payload = `
{
workerVoucherExport${!!params && params.length ? `(${params.join(',')})` : ''}
}`;
return graphql(payload, ACTION_TYPE.EXPORT_WORKER_VOUCHER);
}

export function clearWorkerVoucherExport() {
return (dispatch) => {
dispatch({
type: CLEAR(ACTION_TYPE.EXPORT_WORKER_VOUCHER),
});
};
}
127 changes: 96 additions & 31 deletions src/components/VoucherSearcher.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import React, { useState, useEffect } from 'react';
import { useSelector, connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import { IconButton, Tooltip } from '@material-ui/core';
import {
IconButton, Button, Tooltip, Dialog, DialogActions, DialogTitle, DialogContent,
} from '@material-ui/core';
import VisibilityIcon from '@material-ui/icons/Visibility';

import {
Searcher, useHistory, useModulesManager, useTranslations,
Searcher, useHistory, useModulesManager, useTranslations, downloadExport,
} from '@openimis/fe-core';
import { fetchWorkerVouchers } from '../actions';
import { fetchWorkerVouchers, downloadWorkerVoucher, clearWorkerVoucherExport } from '../actions';
import {
DEFAULT_PAGE_SIZE, MODULE_NAME, REF_ROUTE_WORKER_VOUCHER, ROWS_PER_PAGE_OPTIONS, VOUCHER_RIGHT_SEARCH,
DEFAULT_PAGE_SIZE,
MODULE_NAME,
REF_ROUTE_WORKER_VOUCHER,
ROWS_PER_PAGE_OPTIONS,
VOUCHER_RIGHT_SEARCH,
} from '../constants';
import VoucherFilter from './VoucherFilter';

function VoucherSearcher() {
function VoucherSearcher({ downloadWorkerVoucher, fetchWorkerVouchers, clearWorkerVoucherExport }) {
const history = useHistory();
const dispatch = useDispatch();
const modulesManager = useModulesManager();
const rights = useSelector((state) => state.core?.user?.i_user?.rights ?? []);
const { formatMessage, formatMessageWithValues } = useTranslations(MODULE_NAME, modulesManager);
Expand All @@ -26,11 +32,23 @@ function VoucherSearcher() {
workerVouchers,
workerVouchersPageInfo,
workerVouchersTotalCount,
workerVoucherExport,
errorWorkerVoucherExport,
} = useSelector((state) => state.workerVoucher);
const [failedExport, setFailedExport] = useState(false);
const exportConfiguration = {
exportFields: ['code', 'policyholder', 'insuree', 'status'],
exportFieldsColumns: {
code: formatMessage('code'),
policyholder: formatMessage('employer'),
insuree: formatMessage('worker'),
status: formatMessage('status'),
},
};

const fetchVouchers = (params) => {
try {
dispatch(fetchWorkerVouchers(modulesManager, params));
fetchWorkerVouchers(modulesManager, params);
} catch (error) {
throw new Error(`[VOUCHER_SEARCHER]: Fetching vouchers failed. ${error}`);
}
Expand All @@ -57,9 +75,8 @@ function VoucherSearcher() {

const rowIdentifier = (workerVoucher) => workerVoucher.uuid;

const openWorkerVoucher = (workerVoucher) => rights.includes(VOUCHER_RIGHT_SEARCH) && history.push(
`/${modulesManager.getRef(REF_ROUTE_WORKER_VOUCHER)}/${workerVoucher?.uuid}`,
);
const openWorkerVoucher = (workerVoucher) => rights.includes(VOUCHER_RIGHT_SEARCH)
&& history.push(`/${modulesManager.getRef(REF_ROUTE_WORKER_VOUCHER)}/${workerVoucher?.uuid}`);

const onDoubleClick = (workerVoucher) => openWorkerVoucher(workerVoucher);

Expand All @@ -81,30 +98,78 @@ function VoucherSearcher() {
),
];

useEffect(() => {
if (errorWorkerVoucherExport) {
setFailedExport(true);
}
}, [errorWorkerVoucherExport]);

useEffect(() => {
if (workerVoucherExport) {
downloadExport(workerVoucherExport, `${formatMessage('export.filename')}.csv`)();
clearWorkerVoucherExport();
}
}, [workerVoucherExport]);

const handleExportErrorDialogClose = () => {
setFailedExport(false);
};

const voucherFilter = ({ filters, onChangeFilters }) => (
<VoucherFilter filters={filters} onChangeFilters={onChangeFilters} formatMessage={formatMessage} />
);

return (
<Searcher
module="workerVoucher"
FilterPane={voucherFilter}
fetch={fetchVouchers}
items={workerVouchers}
itemsPageInfo={workerVouchersPageInfo}
fetchedItems={fetchedWorkerVouchers}
fetchingItems={fetchingWorkerVouchers}
errorItems={errorWorkerVouchers}
tableTitle={formatMessageWithValues('workerVoucher.searcherResultsTitle', { workerVouchersTotalCount })}
headers={headers}
itemFormatters={itemFormatters}
sorts={sorts}
rowsPerPageOptions={ROWS_PER_PAGE_OPTIONS}
defaultPageSize={DEFAULT_PAGE_SIZE}
rowIdentifier={rowIdentifier}
onDoubleClick={onDoubleClick}
/>
<>
<Searcher
module="workerVoucher"
FilterPane={voucherFilter}
fetch={fetchVouchers}
items={workerVouchers}
itemsPageInfo={workerVouchersPageInfo}
fetchedItems={fetchedWorkerVouchers}
fetchingItems={fetchingWorkerVouchers}
errorItems={errorWorkerVouchers}
tableTitle={formatMessageWithValues('workerVoucher.searcherResultsTitle', { workerVouchersTotalCount })}
headers={headers}
itemFormatters={itemFormatters}
sorts={sorts}
rowsPerPageOptions={ROWS_PER_PAGE_OPTIONS}
defaultPageSize={DEFAULT_PAGE_SIZE}
rowIdentifier={rowIdentifier}
onDoubleClick={onDoubleClick}
exportable
exportFetch={downloadWorkerVoucher}
exportFields={exportConfiguration.exportFields}
exportFieldsColumns={exportConfiguration.exportFieldsColumns}
exportFieldLabel={formatMessage('export.vouchers')}
chooseExportableColumns
/>
{failedExport && (
<Dialog open={failedExport} fullWidth maxWidth="sm">
<DialogTitle>{errorWorkerVouchers?.message}</DialogTitle>
<DialogContent>
<strong>{`${errorWorkerVouchers?.code}:`}</strong>
{errorWorkerVouchers?.detail}
</DialogContent>
<DialogActions>
<Button onClick={handleExportErrorDialogClose} color="primary" variant="contained">
{formatMessage('close')}
</Button>
</DialogActions>
</Dialog>
)}
</>
);
}

export default VoucherSearcher;
const mapDispatchToProps = (dispatch) => bindActionCreators(
{
downloadWorkerVoucher,
fetchWorkerVouchers,
clearWorkerVoucherExport,
},
dispatch,
);

export default connect(null, mapDispatchToProps)(VoucherSearcher);
47 changes: 41 additions & 6 deletions src/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ import {
parseData,
} from '@openimis/fe-core';
import {
CLEAR,
ERROR, REQUEST, SUCCESS,
CLEAR, ERROR, REQUEST, SUCCESS,
} from './utils/action-type';

export const ACTION_TYPE = {
Expand All @@ -25,6 +24,7 @@ export const ACTION_TYPE = {
SEARCH_VOUCHER_PRICES: 'WORKER_VOUCHER_VOUCHER_PRICES',
MANAGE_VOUCHER_PRICE: 'WORKER_VOUCHER_MANAGE_VOUCHER_PRICE',
DELETE_VOUCHER_PRICE: 'WORKER_VOUCHER_DELETE_VOUCHER_PRICE',
EXPORT_WORKER_VOUCHER: 'WORKER_VOUCHER_VOUCHER_EXPORT',
};

const STORE_STATE = {
Expand All @@ -46,12 +46,14 @@ const STORE_STATE = {
voucherPrices: [],
voucherPricesPageInfo: {},
voucherPricesTotalCount: 0,
fetchingWorkerVoucherExport: false,
fetchedWorkerVoucherExport: false,
workerVoucherExport: null,
workerVoucherExportPageInfo: {},
errorWorkerVoucherExport: null,
};

function reducer(
state = STORE_STATE,
action,
) {
function reducer(state = STORE_STATE, action) {
switch (action.type) {
case REQUEST(ACTION_TYPE.SEARCH_WORKER_VOUCHERS):
return {
Expand Down Expand Up @@ -151,6 +153,39 @@ function reducer(
voucherPricesPageInfo: {},
voucherPricesTotalCount: 0,
};
case REQUEST(ACTION_TYPE.EXPORT_WORKER_VOUCHER):
return {
...state,
fetchingWorkerVoucherExport: true,
fetchedWorkerVoucherExport: false,
workerVoucherExport: null,
workerVoucherExportPageInfo: {},
errorWorkerVoucherExport: null,
};
case SUCCESS(ACTION_TYPE.EXPORT_WORKER_VOUCHER):
return {
...state,
fetchingWorkerVoucherExport: false,
fetchedWorkerVoucherExport: true,
workerVoucherExport: action.payload.data.workerVoucherExport,
workerVoucherExportPageInfo: pageInfo(action.payload.data.workerVoucherExportPageInfo),
errorWorkerVoucherExport: formatGraphQLError(action.payload),
};
case ERROR(ACTION_TYPE.EXPORT_WORKER_VOUCHER):
return {
...state,
fetchingWorkerVoucherExport: false,
errorWorkerVoucherExport: formatServerError(action.payload),
};
case CLEAR(ACTION_TYPE.EXPORT_WORKER_VOUCHER):
return {
...state,
fetchingWorkerVoucherExport: false,
fetchedWorkerVoucherExport: false,
workerVoucherExport: null,
workerVoucherExportPageInfo: {},
errorWorkerVoucherExport: null,
};
case REQUEST(ACTION_TYPE.MUTATION):
return dispatchMutationReq(state, action);
case ERROR(ACTION_TYPE.MUTATION):
Expand Down
2 changes: 2 additions & 0 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
"workerVoucher.searcherResultsTitle": "{workerVouchersTotalCount} Vouchers Found",
"workerVoucher.code": "Code",
"workerVoucher.employer": "Employer",
"workerVoucher.export.filename": "worker_voucher_export",
"workerVoucher.export.vouchers": "DOWNLOAD VOUCHERS",
"workerVoucher.employer.tradename": "Employer Trade Name",
"workerVoucher.employer.code": "Employer Code",
"workerVoucher.worker": "Worker",
Expand Down

0 comments on commit 213a5db

Please sign in to comment.