From 0042c83f974f80b66a28937935b3b0801348cf11 Mon Sep 17 00:00:00 2001 From: olewandowski1 Date: Tue, 28 Nov 2023 12:33:24 +0100 Subject: [PATCH] OM-83: create details page of voucher --- src/actions.js | 12 ++++ src/components/VoucherDetailsEmployer.js | 35 ++++++++++++ src/components/VoucherDetailsPanel.js | 60 ++++++++++++++++++++ src/components/VoucherDetailsVoucher.js | 63 +++++++++++++++++++++ src/components/VoucherDetailsWorker.js | 52 ++++++++++++++++++ src/components/VoucherSearcher.js | 2 +- src/pages/VoucherDetailsPage.js | 70 ++++++++++++++++++++++-- src/reducer.js | 39 +++++++++++++ src/translations/en.json | 8 ++- 9 files changed, 334 insertions(+), 7 deletions(-) create mode 100644 src/components/VoucherDetailsEmployer.js create mode 100644 src/components/VoucherDetailsPanel.js create mode 100644 src/components/VoucherDetailsVoucher.js create mode 100644 src/components/VoucherDetailsWorker.js diff --git a/src/actions.js b/src/actions.js index bd0ae8a..1092bfb 100644 --- a/src/actions.js +++ b/src/actions.js @@ -3,6 +3,7 @@ import { graphql, } from '@openimis/fe-core'; import { ACTION_TYPE } from './reducer'; +import { CLEAR } from './utils/action-type'; const WORKER_VOUCHER_PROJECTION = (modulesManager) => [ 'id', @@ -21,3 +22,14 @@ export function fetchWorkerVouchers(modulesManager, params) { const payload = formatPageQueryWithCount('workerVoucher', queryParams, WORKER_VOUCHER_PROJECTION(modulesManager)); return graphql(payload, ACTION_TYPE.SEARCH_WORKER_VOUCHERS); } + +export function fetchWorkerVoucher(modulesManager, params) { + const payload = formatPageQueryWithCount('workerVoucher', params, WORKER_VOUCHER_PROJECTION(modulesManager)); + return graphql(payload, ACTION_TYPE.GET_WORKER_VOUCHER); +} + +export const clearWorkerVoucher = () => (dispatch) => { + dispatch({ + type: CLEAR(ACTION_TYPE.GET_WORKER_VOUCHER), + }); +}; diff --git a/src/components/VoucherDetailsEmployer.js b/src/components/VoucherDetailsEmployer.js new file mode 100644 index 0000000..933dedc --- /dev/null +++ b/src/components/VoucherDetailsEmployer.js @@ -0,0 +1,35 @@ +import React from 'react'; + +import { Grid, Divider } from '@material-ui/core'; + +import { TextInput } from '@openimis/fe-core'; + +function VoucherDetailsEmployer({ + workerVoucher, classes, readOnly, +}) { + return ( + <> + + + + + + + + + + + ); +} + +export default VoucherDetailsEmployer; diff --git a/src/components/VoucherDetailsPanel.js b/src/components/VoucherDetailsPanel.js new file mode 100644 index 0000000..6430d90 --- /dev/null +++ b/src/components/VoucherDetailsPanel.js @@ -0,0 +1,60 @@ +import React from 'react'; + +import { Divider, Grid, Typography } from '@material-ui/core'; +import { makeStyles } from '@material-ui/styles'; + +import { FormattedMessage } from '@openimis/fe-core'; +import VoucherDetailsEmployer from './VoucherDetailsEmployer'; +import VoucherDetailsVoucher from './VoucherDetailsVoucher'; +import VoucherDetailsWorker from './VoucherDetailsWorker'; + +const useStyles = makeStyles((theme) => ({ + tableTitle: theme.table.title, + item: theme.paper.item, + fullHeight: { + height: '100%', + }, +})); + +function VoucherDetailsPanel({ workerVoucher, readOnly = true, formatMessage }) { + const classes = useStyles(); + + return ( + <> + + + + + + + + + + + + + + + ); +} + +export default VoucherDetailsPanel; diff --git a/src/components/VoucherDetailsVoucher.js b/src/components/VoucherDetailsVoucher.js new file mode 100644 index 0000000..0a35910 --- /dev/null +++ b/src/components/VoucherDetailsVoucher.js @@ -0,0 +1,63 @@ +import React from 'react'; + +import { Grid, Divider } from '@material-ui/core'; + +import { PublishedComponent, TextInput } from '@openimis/fe-core'; +import WorkerVoucherStatusPicker from '../pickers/WorkerVoucherStatusPicker'; + +function VoucherDetailsVoucher({ + workerVoucher, classes, readOnly, formatMessage, +}) { + return ( + <> + + + + + + + + + + + + + + + + + + + + ); +} + +export default VoucherDetailsVoucher; diff --git a/src/components/VoucherDetailsWorker.js b/src/components/VoucherDetailsWorker.js new file mode 100644 index 0000000..9edf0ff --- /dev/null +++ b/src/components/VoucherDetailsWorker.js @@ -0,0 +1,52 @@ +import React from 'react'; + +import { Grid, Divider } from '@material-ui/core'; + +import { PublishedComponent, TextInput } from '@openimis/fe-core'; + +function VoucherDetailsWorker({ + workerVoucher, classes, readOnly, +}) { + return ( + <> + + + + + + + + + + + + + + + + + ); +} + +export default VoucherDetailsWorker; diff --git a/src/components/VoucherSearcher.js b/src/components/VoucherSearcher.js index 9e2acf1..c035189 100644 --- a/src/components/VoucherSearcher.js +++ b/src/components/VoucherSearcher.js @@ -58,7 +58,7 @@ 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}}`, + `/${modulesManager.getRef(REF_ROUTE_WORKER_VOUCHER)}/${workerVoucher?.uuid}`, ); const onDoubleClick = (workerVoucher) => openWorkerVoucher(workerVoucher); diff --git a/src/pages/VoucherDetailsPage.js b/src/pages/VoucherDetailsPage.js index 09f1c66..6a2e897 100644 --- a/src/pages/VoucherDetailsPage.js +++ b/src/pages/VoucherDetailsPage.js @@ -1,10 +1,70 @@ -import React from 'react'; +import React, { useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; + +import { makeStyles } from '@material-ui/styles'; + +import { + Form, + Helmet, + useHistory, + useModulesManager, + useTranslations, +} from '@openimis/fe-core'; +import { clearWorkerVoucher, fetchWorkerVoucher } from '../actions'; +import { EMPTY_STRING, MODULE_NAME, VOUCHER_RIGHT_SEARCH } from '../constants'; +import VoucherDetailsPanel from '../components/VoucherDetailsPanel'; + +const useStyles = makeStyles((theme) => ({ + page: theme.page, +})); + +function VoucherDetailsPage({ match }) { + const classes = useStyles(); + const dispatch = useDispatch(); + const modulesManager = useModulesManager(); + const history = useHistory(); + const { formatMessage, formatMessageWithValues } = useTranslations(MODULE_NAME, modulesManager); + const rights = useSelector((state) => (state.core?.user?.i_user?.rights ?? [])); + const workerVoucherUuid = match?.params?.voucher_uuid; + const { workerVoucher, fetchingWorkerVoucher, errorWorkerVoucher } = useSelector((state) => state.workerVoucher); + + const titleParams = (workerVoucher) => ({ + code: workerVoucher?.code ?? EMPTY_STRING, + }); + + useEffect(() => { + try { + if (workerVoucherUuid) { + const params = [`id: "${workerVoucherUuid}"`]; + dispatch(fetchWorkerVoucher(modulesManager, params)); + } + } catch (error) { + throw new Error(`[VOUCHER_DETAILS_PAGE]: Fetching worker voucher failed. ${error}`); + } + + return () => dispatch(clearWorkerVoucher()); + }, [workerVoucherUuid]); -function VoucherDetailsPage() { return ( -
- VoucherDetailsPage -
+ rights.includes(VOUCHER_RIGHT_SEARCH) && ( +
+ +
history.goBack()} + HeadPanel={VoucherDetailsPanel} + readOnly + formatMessage={formatMessage} + rights={rights} + /> +
+ ) ); } diff --git a/src/reducer.js b/src/reducer.js index cfc0c82..2a643de 100644 --- a/src/reducer.js +++ b/src/reducer.js @@ -8,11 +8,13 @@ import { parseData, } from '@openimis/fe-core'; import { + CLEAR, ERROR, REQUEST, SUCCESS, } from './utils/action-type'; export const ACTION_TYPE = { SEARCH_WORKER_VOUCHERS: 'WORKER_VOUCHER_WORKER_VOUCHERS', + GET_WORKER_VOUCHER: 'WORKER_VOUCHER_GET_WORKER_VOUCHER', }; const STORE_STATE = { @@ -22,6 +24,10 @@ const STORE_STATE = { workerVouchers: [], workerVouchersPageInfo: {}, workerVouchersTotalCount: 0, + fetchingWorkerVoucher: false, + fetchedWorkerVoucher: false, + workerVoucher: {}, + errorWorkerVoucher: null, }; function reducer( @@ -58,6 +64,39 @@ function reducer( fetchingWorkerVouchers: false, errorWorkerVouchers: formatServerError(action.payload), }; + case REQUEST(ACTION_TYPE.GET_WORKER_VOUCHER): + return { + ...state, + fetchingWorkerVoucher: true, + fetchedWorkerVoucher: false, + workerVoucher: {}, + errorWorkerVoucher: null, + }; + case SUCCESS(ACTION_TYPE.GET_WORKER_VOUCHER): + return { + ...state, + fetchingWorkerVoucher: false, + fetchedWorkerVoucher: true, + workerVoucher: parseData(action.payload.data.workerVoucher)?.map((voucher) => ({ + ...voucher, + uuid: decodeId(voucher.id), + }))?.[0], + errorWorkerVoucher: formatGraphQLError(action.payload), + }; + case ERROR(ACTION_TYPE.GET_WORKER_VOUCHER): + return { + ...state, + fetchingWorkerVoucher: false, + errorWorkerVoucher: formatServerError(action.payload), + }; + case CLEAR(ACTION_TYPE.GET_WORKER_VOUCHER): + return { + ...state, + fetchingWorkerVoucher: false, + fetchedWorkerVoucher: false, + workerVoucher: {}, + errorWorkerVoucher: null, + }; default: return state; } diff --git a/src/translations/en.json b/src/translations/en.json index 43a3082..7e86570 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -11,9 +11,12 @@ "workerVoucher.worker": "Worker", "workerVoucher.worker.code": "Worker National ID", "workerVoucher.worker.lastName": "Worker Last Name", + "workerVoucher.worker.otherNames": "Worker Other Names", + "workerVoucher.worker.dob": "Worker Date of Birth", "workerVoucher.status": "Status", "workerVoucher.assignedDate": "Assigned Date", "workerVoucher.expiryDate": "Expiry Date", + "workerVoucher.createdDate": "Created Date", "workerVoucher.tooltip.details": "View details", "workerVoucher.placeholder.any": "Any", "workerVoucher.status.AWAITING_PAYMENT": "AWAITING PAYMENT", @@ -21,5 +24,8 @@ "workerVoucher.status.ASSIGNED": "ASSIGNED", "workerVoucher.status.EXPIRED": "EXPIRED", "workerVoucher.status.CANCELED": "CANCELED", - "workerVoucher.status.CLOSED": "CLOSED" + "workerVoucher.status.CLOSED": "CLOSED", + "workerVoucher.VoucherDetailsPage.title": "Worker Voucher - {code}", + "workerVoucher.VoucherDetailsPanel.subtitle": "Voucher's General Information" + }