lamassu-server/new-lamassu-admin/src/pages/OperatorInfo/SMSNotices/SMSNotices.js
2022-02-24 21:48:20 +00:00

267 lines
6.7 KiB
JavaScript

import { useQuery, useMutation } from '@apollo/react-hooks'
import { makeStyles, Paper } from '@material-ui/core'
import gql from 'graphql-tag'
import * as R from 'ramda'
import React, { useState } from 'react'
import { HoverableTooltip } from 'src/components/Tooltip'
import { IconButton } from 'src/components/buttons'
import { Switch } from 'src/components/inputs'
import DataTable from 'src/components/tables/DataTable'
import { H4, P, Label3 } from 'src/components/typography'
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg'
import { ReactComponent as ExpandIconClosed } from 'src/styling/icons/action/expand/closed.svg'
import { ReactComponent as ExpandIconOpen } from 'src/styling/icons/action/expand/open.svg'
import { ReactComponent as WhiteLogo } from 'src/styling/icons/menu/logo-white.svg'
import { formatDate } from 'src/utils/timezones'
import styles from './SMSNotices.styles'
import CustomSMSModal from './SMSNoticesModal'
const useStyles = makeStyles(styles)
const GET_SMS_NOTICES = gql`
query SMSNotices {
SMSNotices {
id
event
message
messageName
enabled
allowToggle
}
config
}
`
const EDIT_SMS_NOTICE = gql`
mutation editSMSNotice($id: ID!, $event: SMSNoticeEvent!, $message: String!) {
editSMSNotice(id: $id, event: $event, message: $message) {
id
}
}
`
const ENABLE_SMS_NOTICE = gql`
mutation enableSMSNotice($id: ID!) {
enableSMSNotice(id: $id) {
id
}
}
`
const DISABLE_SMS_NOTICE = gql`
mutation disableSMSNotice($id: ID!) {
disableSMSNotice(id: $id) {
id
}
}
`
const multiReplace = (str, obj) => {
var re = new RegExp(Object.keys(obj).join('|'), 'gi')
return str.replace(re, function(matched) {
return obj[matched.toLowerCase()]
})
}
const formatContent = content => {
const fragments = R.split(/\n/)(content)
return R.map((it, idx) => {
if (idx === fragments.length) return <>{it}</>
return (
<>
{it}
<br />
</>
)
}, fragments)
}
const TOOLTIPS = {
smsCode: ``,
cashOutDispenseReady: ``,
smsReceipt: formatContent(`The contents of this notice will be appended to the end of the SMS receipt sent, and not replace it.\n
To edit the contents of the SMS receipt, please go to the 'Receipt' tab`)
}
const SMSPreview = ({ sms, coords, timezone }) => {
const classes = useStyles(coords)
const matches = {
'#code': 123,
'#timestamp': formatDate(new Date(), timezone, 'HH:mm')
}
return (
<div className={classes.smsPreview}>
<div className={classes.smsPreviewContainer}>
<div className={classes.smsPreviewIcon}>
<WhiteLogo width={22} height={22} />
</div>
<Paper className={classes.smsPreviewContent}>
<P noMargin>
{R.isEmpty(sms?.message) ? (
<i>No content available</i>
) : (
formatContent(multiReplace(sms?.message, matches))
)}
</P>
</Paper>
<Label3>{formatDate(new Date(), timezone, 'HH:mm')}</Label3>
</div>
</div>
)
}
const SMSNotices = () => {
const classes = useStyles()
const [showModal, setShowModal] = useState(false)
const [selectedSMS, setSelectedSMS] = useState(null)
const [previewOpen, setPreviewOpen] = useState(false)
const [previewCoords, setPreviewCoords] = useState({ x: 0, y: 0 })
const [errorMsg, setErrorMsg] = useState('')
const { data: messagesData, loading: messagesLoading } = useQuery(
GET_SMS_NOTICES
)
const timezone = R.path(['config', 'locale_timezone'])(messagesData)
const [editMessage] = useMutation(EDIT_SMS_NOTICE, {
onError: ({ msg }) => setErrorMsg(msg),
refetchQueries: () => ['SMSNotices']
})
const [enableMessage] = useMutation(ENABLE_SMS_NOTICE, {
onError: ({ msg }) => setErrorMsg(msg),
refetchQueries: () => ['SMSNotices']
})
const [disableMessage] = useMutation(DISABLE_SMS_NOTICE, {
onError: ({ msg }) => setErrorMsg(msg),
refetchQueries: () => ['SMSNotices']
})
const loading = messagesLoading
const handleClose = () => {
setShowModal(false)
setSelectedSMS(null)
}
const elements = [
{
header: 'Message name',
width: 500,
size: 'sm',
textAlign: 'left',
view: it =>
!R.isEmpty(TOOLTIPS[it.event]) ? (
<div className={classes.messageWithTooltip}>
{R.prop('messageName', it)}
<HoverableTooltip width={250}>
<P>{TOOLTIPS[it.event]}</P>
</HoverableTooltip>
</div>
) : (
R.prop('messageName', it)
)
},
{
header: 'Edit',
width: 100,
size: 'sm',
textAlign: 'center',
view: it => (
<IconButton
onClick={() => {
setPreviewOpen(false)
setSelectedSMS(it)
setShowModal(true)
}}>
<EditIcon />
</IconButton>
)
},
{
header: 'Enable',
width: 100,
size: 'sm',
textAlign: 'center',
view: it => (
<Switch
disabled={!it.allowToggle}
onClick={() => {
it.enabled
? disableMessage({ variables: { id: it.id } })
: enableMessage({ variables: { id: it.id } })
}}
checked={it.enabled}
/>
)
},
{
header: '',
width: 100,
size: 'sm',
textAlign: 'center',
view: it => (
<IconButton
onClick={e => {
setSelectedSMS(it)
setPreviewCoords({
x: e.currentTarget.getBoundingClientRect().right + 50,
y:
window.innerHeight -
5 -
e.currentTarget.getBoundingClientRect().bottom
})
R.equals(selectedSMS, it)
? setPreviewOpen(!previewOpen)
: setPreviewOpen(true)
}}>
{R.equals(selectedSMS, it) && previewOpen ? (
<ExpandIconOpen />
) : (
<ExpandIconClosed />
)}
</IconButton>
)
}
]
return (
<>
<div className={classes.header}>
<H4>SMS notices</H4>
</div>
{showModal && (
<CustomSMSModal
showModal={showModal}
onClose={handleClose}
sms={selectedSMS}
creationError={errorMsg}
submit={editMessage}
/>
)}
{previewOpen && (
<SMSPreview
sms={selectedSMS}
coords={previewCoords}
timezone={timezone}
/>
)}
<DataTable
emptyText="No SMS notices so far"
elements={elements}
loading={loading}
data={R.path(['SMSNotices'])(messagesData)}
/>
</>
)
}
export default SMSNotices