Skip to content

Commit

Permalink
OM-330: add qr codes to vouchers (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
olewandowski1 authored Oct 23, 2024
1 parent 7acf16f commit b987c7f
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 50 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"no-shadow": "off", // disabled due to use of bindActionCreators
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], // disabled due to naming consistency with other modules
"import/no-unresolved": "off", // disable due to module architecture. For modules most references are marked as unresolved
"max-len": ["error", { "code": 120 }]
"max-len": ["error", { "code": 120 }],
"import/no-extraneous-dependencies": "off"
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"dist"
],
"dependencies": {
"react-qr-code": "^2.0.15",
"react-to-print": "^2.15.1"
}
}
2 changes: 2 additions & 0 deletions src/components/VoucherDetailsPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
FormattedMessage, useModulesManager, useHistory, historyPush,
} from '@openimis/fe-core';
import { PRINTABLE, REF_ROUTE_BILL, VOUCHER_RIGHT_SEARCH } from '../constants';
import { isTheVoucherExpired } from '../utils/utils';
import VoucherDetailsEmployer from './VoucherDetailsEmployer';
import VoucherDetailsVoucher from './VoucherDetailsVoucher';
import VoucherDetailsWorker from './VoucherDetailsWorker';
Expand Down Expand Up @@ -67,6 +68,7 @@ function VoucherDetailsPanel({
variant="contained"
color="primary"
startIcon={<PrintIcon />}
disabled={!workerVoucher.billId || isTheVoucherExpired(workerVoucher)}
onClick={(e) => {
e.preventDefault();
handlePrint(null, () => voucherPrintTemplateRef.current);
Expand Down
28 changes: 22 additions & 6 deletions src/components/VoucherDetailsPrintTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, {
forwardRef, useState, useEffect, useMemo,
} from 'react';
import { useDispatch } from 'react-redux';
import clsx from 'clsx';

import { Divider } from '@material-ui/core';
import { makeStyles } from '@material-ui/styles';
Expand All @@ -11,6 +12,7 @@ import {
EMPTY_STRING, MODULE_NAME, REF_GET_BILL_LINE_ITEM, WORKER_VOUCHER_STATUS,
} from '../constants';
import { extractEmployerName, extractWorkerName } from '../utils/utils';
import VoucherQRCode from './VoucherQRCode';

const useStyles = makeStyles((theme) => ({
'@global': {
Expand All @@ -24,7 +26,7 @@ const useStyles = makeStyles((theme) => ({
display: 'flex',
flexDirection: 'row',
height: '320px',
padding: '24px',
padding: '12px',
justifyContent: 'space-between',
borderLeft: `10px solid ${theme.palette.primary.main}`,
borderRight: `10px solid ${theme.palette.primary.main}`,
Expand All @@ -38,14 +40,14 @@ const useStyles = makeStyles((theme) => ({
fontSize: '48px',
fontWeight: 900,
letterSpacing: '-2px',
textAlign: 'right',
textAlign: 'left',
},
annotation: {
fontSize: '12px',
fontStyle: 'italic',
},
voucherTitle: {
fontSize: '32px',
fontSize: '28px',
fontWeight: 900,
textTransform: 'uppercase',
},
Expand All @@ -57,11 +59,16 @@ const useStyles = makeStyles((theme) => ({
fontSize: '16px',
fontWeight: 500,
},
manualFill: {
fields: {
display: 'flex',
flexDirection: 'column',
},
manualFill: {
gap: '16px',
},
assignedFields: {
gap: '4px',
},
}));

const VoucherDetailsPrintTemplate = forwardRef(({ workerVoucher, logo }, ref) => {
Expand Down Expand Up @@ -113,7 +120,13 @@ const VoucherDetailsPrintTemplate = forwardRef(({ workerVoucher, logo }, ref) =>
</p>
</div>

<div className={classes.manualFill}>
<div
className={clsx({
[classes.fields]: true,
[classes.manualFill]: !isAssignedStatus,
[classes.assignedFields]: isAssignedStatus,
})}
>
<div>
<p className={classes.workerInfo}>{extractWorkerName(workerVoucher.insuree, isAssignedStatus)}</p>
<Divider />
Expand All @@ -126,6 +139,7 @@ const VoucherDetailsPrintTemplate = forwardRef(({ workerVoucher, logo }, ref) =>
<Divider />
<p className={classes.annotation}>{formatMessage('workerVoucher.template.validOn')}</p>
</div>
<p className={classes.voucherValue}>{`${voucherValue || 0} ${formatMessage('currency')}`}</p>
</div>
</div>

Expand All @@ -137,7 +151,9 @@ const VoucherDetailsPrintTemplate = forwardRef(({ workerVoucher, logo }, ref) =>
alt="Logo of Ministerul Muncii și Protecţiei Sociale al Republicii Moldova"
/>
</div>
<p className={classes.voucherValue}>{`${voucherValue || 0} ${formatMessage('currency')}`}</p>
<div>
<VoucherQRCode voucher={workerVoucher} bgColor="#FFFFFF" size={256} />
</div>
</div>
</div>
);
Expand Down
90 changes: 48 additions & 42 deletions src/components/VoucherDetailsVoucher.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,61 @@ import { Grid, Divider } from '@material-ui/core';

import { PublishedComponent, TextInput } from '@openimis/fe-core';
import WorkerVoucherStatusPicker from '../pickers/WorkerVoucherStatusPicker';
import VoucherQRCode from './VoucherQRCode';

function VoucherDetailsVoucher({
workerVoucher, classes, readOnly, formatMessage,
}) {
return (
<>
<Grid container>
<Grid item xs={3} className={classes.item}>
<TextInput
module="workerVoucher"
label="workerVoucher.code"
value={workerVoucher?.code}
readOnly={readOnly}
/>
<Grid container style={{ marginTop: '12px' }}>
<Grid xs={3}>
<VoucherQRCode voucher={workerVoucher} />
</Grid>
<Grid item xs={3} className={classes.item}>
<WorkerVoucherStatusPicker
nullLabel={formatMessage('workerVoucher.placeholder.any')}
withLabel
value={workerVoucher?.status}
readOnly={readOnly}
/>
</Grid>
<Grid item xs={3} className={classes.item}>
<PublishedComponent
pubRef="core.DatePicker"
module="workerVoucher"
label="workerVoucher.assignedDate"
value={workerVoucher?.assignedDate}
readOnly={readOnly}
/>
</Grid>
<Grid item xs={3} className={classes.item}>
<PublishedComponent
pubRef="core.DatePicker"
module="workerVoucher"
label="workerVoucher.expiryDate"
value={workerVoucher?.expiryDate}
readOnly={readOnly}
/>
</Grid>
<Grid item xs={3} className={classes.item}>
<PublishedComponent
pubRef="core.DatePicker"
module="workerVoucher"
label="workerVoucher.createdDate"
value={workerVoucher?.dateCreated}
readOnly={readOnly}
/>
<Grid container xs={9}>
<Grid item xs={4} className={classes.item}>
<TextInput
module="workerVoucher"
label="workerVoucher.code"
value={workerVoucher?.code}
readOnly={readOnly}
/>
</Grid>
<Grid item xs={4} className={classes.item}>
<WorkerVoucherStatusPicker
nullLabel={formatMessage('workerVoucher.placeholder.any')}
withLabel
value={workerVoucher?.status}
readOnly={readOnly}
/>
</Grid>
<Grid item xs={4} className={classes.item}>
<PublishedComponent
pubRef="core.DatePicker"
module="workerVoucher"
label="workerVoucher.assignedDate"
value={workerVoucher?.assignedDate}
readOnly={readOnly}
/>
</Grid>
<Grid item xs={4} className={classes.item}>
<PublishedComponent
pubRef="core.DatePicker"
module="workerVoucher"
label="workerVoucher.expiryDate"
value={workerVoucher?.expiryDate}
readOnly={readOnly}
/>
</Grid>
<Grid item xs={4} className={classes.item}>
<PublishedComponent
pubRef="core.DatePicker"
module="workerVoucher"
label="workerVoucher.createdDate"
value={workerVoucher?.dateCreated}
readOnly={readOnly}
/>
</Grid>
</Grid>
</Grid>
<Divider style={{ margin: '12px 0' }} />
Expand Down
44 changes: 44 additions & 0 deletions src/components/VoucherQRCode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import QRCode from 'react-qr-code';
import { makeStyles } from '@material-ui/styles';

import { Grid } from '@material-ui/core';

const useStyles = makeStyles(() => ({
qrContainer: {
height: 'auto',
margin: '12px auto',
maxWidth: 128,
width: '100%',
},
qrCode: {
height: 'auto',
maxWidth: '100%',
width: '100%',
},
}));

export default function VoucherQRCode({ voucher, bgColor = '#e4f2ff' }) {
if (!voucher) {
return null;
}

const classes = useStyles();
const voucherUrl = new URL(`${window.location.origin}${process.env.PUBLIC_URL}/voucher/check/${voucher.code}`);

return (
<Grid item xs={12}>
<div className={classes.qrContainer}>
<QRCode
size={128}
className={classes.qrCode}
value={voucherUrl.toString()}
viewBox="0 0 256 256"
level="H"
bgColor={bgColor}
fgColor="#000000"
/>
</div>
</Grid>
);
}
5 changes: 4 additions & 1 deletion src/utils/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable import/prefer-default-export */

import { baseApiUrl, parseData } from '@openimis/fe-core';
import { MPAY_BILL_URL } from '../constants';
import { MPAY_BILL_URL, WORKER_VOUCHER_STATUS } from '../constants';
import { fetchMutation } from '../actions';

const fetchMPayArgs = async (url) => {
Expand Down Expand Up @@ -70,3 +70,6 @@ export const getLastMutationLog = async (dispatch, mutationId) => {

return parseData(mutation.payload.data.mutationLogs)?.[0];
};

export const isTheVoucherExpired = (voucher) => voucher.status === WORKER_VOUCHER_STATUS.EXPIRED
|| new Date(voucher.expiryDate) < new Date();

0 comments on commit b987c7f

Please sign in to comment.