feat: added an editable option for the receipt printing active status
feat: create an EditableProperty component feat: added boolean properties table and missing properties chore: integrated receipt printing page on op info page fix: fixed style issues in the boolean properties table feat: added a custom prefixText on the editable property component chore: commented out currently unused features fix: fixed boolean properties table color chore: removed debug logs fix: boolean properties table cancel button was saving instead of canceling fix: receipt printing properties where wrong (customText currently isn't used, and customerNameOrPhoneNumber was using the wrong property)
This commit is contained in:
parent
840788e044
commit
5256301eff
9 changed files with 353 additions and 23 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import classnames from 'classnames'
|
||||
import React, { useState, memo } from 'react'
|
||||
|
||||
import { Link } from 'src/components/buttons'
|
||||
|
|
@ -30,6 +31,7 @@ const BooleanPropertiesTable = memo(
|
|||
}
|
||||
|
||||
const innerCancel = () => {
|
||||
setRadioGroupValues(elements)
|
||||
setEditing(false)
|
||||
}
|
||||
|
||||
|
|
@ -79,23 +81,31 @@ const BooleanPropertiesTable = memo(
|
|||
{radioGroupValues &&
|
||||
radioGroupValues.map((element, idx) => (
|
||||
<TableRow key={idx} size="sm" className={classes.tableRow}>
|
||||
<TableCell className={classes.tableCell}>
|
||||
<TableCell className={classes.leftTableCell}>
|
||||
{element.display}
|
||||
{editing && (
|
||||
<RadioGroup
|
||||
options={radioButtonOptions}
|
||||
value={element.value}
|
||||
onChange={event =>
|
||||
handleRadioButtons(
|
||||
element.name,
|
||||
event.target.value === 'true'
|
||||
)
|
||||
}
|
||||
className={classes.radioButtons}
|
||||
/>
|
||||
)}
|
||||
{!editing && <BooleanCell value={element.value} />}
|
||||
</TableCell>
|
||||
{editing && (
|
||||
<RadioGroup
|
||||
options={radioButtonOptions}
|
||||
value={element.value}
|
||||
onChange={event =>
|
||||
handleRadioButtons(
|
||||
element.name,
|
||||
event.target.value === 'true'
|
||||
)
|
||||
}
|
||||
className={classnames(
|
||||
classes.radioButtons,
|
||||
classes.rightTableCell
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{!editing && (
|
||||
<BooleanCell
|
||||
className={classes.rightTableCell}
|
||||
value={element.value}
|
||||
/>
|
||||
)}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import baseStyles from 'src/pages/Logs.styles'
|
||||
import { tableCellColor, zircon } from 'src/styling/variables'
|
||||
import { backgroundColor, zircon } from 'src/styling/variables'
|
||||
|
||||
const { fillColumn } = baseStyles
|
||||
|
||||
|
|
@ -14,20 +14,28 @@ const booleanPropertiesTableStyles = {
|
|||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
'&:nth-child(even)': {
|
||||
backgroundColor: tableCellColor
|
||||
backgroundColor: backgroundColor
|
||||
},
|
||||
'&:nth-child(odd)': {
|
||||
backgroundColor: zircon
|
||||
},
|
||||
minHeight: 32,
|
||||
height: 'auto',
|
||||
padding: [[8, 16, 8, 24]],
|
||||
boxShadow: '0 0 0 0 rgba(0, 0, 0, 0)'
|
||||
},
|
||||
tableCell: {
|
||||
leftTableCell: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
width: '100%',
|
||||
height: 32,
|
||||
padding: [[5, 14, 5, 20]]
|
||||
justifyContent: 'left',
|
||||
width: 200,
|
||||
padding: [0]
|
||||
},
|
||||
rightTableCell: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'right',
|
||||
padding: [0]
|
||||
},
|
||||
transparentButton: {
|
||||
'& > *': {
|
||||
|
|
@ -51,7 +59,7 @@ const booleanPropertiesTableStyles = {
|
|||
radioButtons: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
marginRight: -15
|
||||
margin: [-15]
|
||||
},
|
||||
rightLink: {
|
||||
marginLeft: '20px'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import React, { useState, memo } from 'react'
|
||||
|
||||
import { Link } from 'src/components/buttons'
|
||||
import { RadioGroup } from 'src/components/inputs'
|
||||
import { H4, P } from 'src/components/typography'
|
||||
import { ReactComponent as EditIconDisabled } from 'src/styling/icons/action/edit/disabled.svg'
|
||||
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg'
|
||||
|
||||
import { editablePropertyStyles } from './EditableProperty.styles'
|
||||
|
||||
const useStyles = makeStyles(editablePropertyStyles)
|
||||
|
||||
const EditableProperty = memo(
|
||||
({ title, prefixText, disabled, options, code, save }) => {
|
||||
const [editing, setEditing] = useState(false)
|
||||
const [currentCode, setCurrentCode] = useState(code)
|
||||
|
||||
const classes = useStyles()
|
||||
|
||||
const innerSave = () => {
|
||||
save(currentCode)
|
||||
setEditing(false)
|
||||
}
|
||||
|
||||
const innerCancel = () => setEditing(false)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={classes.rowWrapper}>
|
||||
<H4>{title}</H4>
|
||||
{editing ? (
|
||||
<div className={classes.leftSpace}>
|
||||
<Link
|
||||
className={classes.leftSpace}
|
||||
onClick={innerCancel}
|
||||
color="secondary">
|
||||
Cancel
|
||||
</Link>
|
||||
<Link
|
||||
className={classes.leftSpace}
|
||||
onClick={innerSave}
|
||||
color="primary">
|
||||
Save
|
||||
</Link>
|
||||
</div>
|
||||
) : (
|
||||
<div className={classes.transparentButton}>
|
||||
<button disabled={disabled} onClick={() => setEditing(true)}>
|
||||
{disabled ? <EditIconDisabled /> : <EditIcon />}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{editing ? (
|
||||
<RadioGroup
|
||||
options={options}
|
||||
value={currentCode}
|
||||
onChange={event => setCurrentCode(event.target.value)}
|
||||
className={classes.radioButtons}
|
||||
/>
|
||||
) : (
|
||||
<P>
|
||||
{`${prefixText} ${options
|
||||
.find(it => it.code === currentCode)
|
||||
.display.toLowerCase()}`}
|
||||
</P>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
export default EditableProperty
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
const editablePropertyStyles = {
|
||||
transparentButton: {
|
||||
'& > *': {
|
||||
margin: 'auto 12px'
|
||||
},
|
||||
'& button': {
|
||||
border: 'none',
|
||||
backgroundColor: 'transparent',
|
||||
cursor: 'pointer'
|
||||
}
|
||||
},
|
||||
rowWrapper: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
position: 'relative',
|
||||
flex: 'wrap'
|
||||
},
|
||||
rightAligned: {
|
||||
display: 'flex',
|
||||
position: 'absolute',
|
||||
right: 0
|
||||
},
|
||||
radioButtons: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
leftSpace: {
|
||||
marginLeft: '20px'
|
||||
}
|
||||
}
|
||||
|
||||
export { editablePropertyStyles }
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import EditableProperty from './EditableProperty'
|
||||
|
||||
export { EditableProperty }
|
||||
|
|
@ -9,6 +9,7 @@ import logsStyles from '../Logs.styles'
|
|||
|
||||
import CoinAtmRadar from './CoinATMRadar'
|
||||
import ContactInfo from './ContactInfo'
|
||||
import ReceiptPrinting from './ReceiptPrinting'
|
||||
import TermsConditions from './TermsConditions'
|
||||
|
||||
const localStyles = {
|
||||
|
|
@ -52,6 +53,7 @@ const OperatorInfo = () => {
|
|||
/>
|
||||
<div className={classes.contentWrapper}>
|
||||
{isSelected(CONTACT_INFORMATION) && <ContactInfo />}
|
||||
{isSelected(RECEIPT) && <ReceiptPrinting />}
|
||||
{isSelected(TERMS_CONDITIONS) && <TermsConditions />}
|
||||
{isSelected(COIN_ATM_RADAR) && <CoinAtmRadar />}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,187 @@
|
|||
// import { makeStyles } from '@material-ui/core/styles'
|
||||
import { useQuery, useMutation } from '@apollo/react-hooks'
|
||||
import { gql } from 'apollo-boost'
|
||||
import React, { useState, memo } from 'react'
|
||||
|
||||
import { BooleanPropertiesTable } from 'src/components/booleanPropertiesTable'
|
||||
import { EditableProperty } from 'src/components/editableProperty'
|
||||
// import { ActionButton } from 'src/components/buttons'
|
||||
// import { ReactComponent as UploadIcon } from 'src/styling/icons/button/upload/zodiac.svg'
|
||||
// import { ReactComponent as UploadIconInverse } from 'src/styling/icons/button/upload/white.svg'
|
||||
// import { TextInput } from 'src/components/inputs'
|
||||
|
||||
// import { mainStyles } from './ReceiptPrinting.styles'
|
||||
|
||||
// const useStyles = makeStyles(mainStyles)
|
||||
|
||||
const initialValues = {
|
||||
active: 'off',
|
||||
// logo: false,
|
||||
operatorWebsite: false,
|
||||
operatorEmail: false,
|
||||
operatorPhone: false,
|
||||
companyRegistration: false,
|
||||
machineLocation: false,
|
||||
customerNameOrPhoneNumber: false,
|
||||
// commission: false,
|
||||
exchangeRate: false,
|
||||
addressQRCode: false
|
||||
// customText: false,
|
||||
// customTextContent: ''
|
||||
}
|
||||
|
||||
const GET_CONFIG = gql`
|
||||
{
|
||||
config
|
||||
}
|
||||
`
|
||||
|
||||
const SAVE_CONFIG = gql`
|
||||
mutation Save($config: JSONObject) {
|
||||
saveConfig(config: $config)
|
||||
}
|
||||
`
|
||||
|
||||
const receiptPrintingOptions = [
|
||||
{
|
||||
code: 'off',
|
||||
display: 'Off'
|
||||
},
|
||||
{
|
||||
code: 'optional',
|
||||
display: 'Optional (ask user)'
|
||||
},
|
||||
{
|
||||
code: 'on',
|
||||
display: 'On'
|
||||
}
|
||||
]
|
||||
|
||||
const ReceiptPrinting = memo(() => {
|
||||
const [receiptPrintingConfig, setReceiptPrintingConfig] = useState(null)
|
||||
|
||||
// const classes = useStyles()
|
||||
|
||||
// TODO: treat errors on useMutation and useQuery
|
||||
const [saveConfig] = useMutation(SAVE_CONFIG, {
|
||||
onCompleted: configResponse =>
|
||||
setReceiptPrintingConfig(configResponse.saveConfig.receiptPrinting)
|
||||
})
|
||||
useQuery(GET_CONFIG, {
|
||||
onCompleted: configResponse => {
|
||||
setReceiptPrintingConfig(
|
||||
configResponse?.config?.receiptPrinting ?? initialValues
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
const save = it =>
|
||||
saveConfig({ variables: { config: { receiptPrinting: it } } })
|
||||
|
||||
if (!receiptPrintingConfig) return null
|
||||
|
||||
return (
|
||||
<>
|
||||
<EditableProperty
|
||||
title={'Receipt options'}
|
||||
prefixText={'Receipt printing'}
|
||||
disabled={false}
|
||||
options={receiptPrintingOptions}
|
||||
code={receiptPrintingConfig.active}
|
||||
save={it =>
|
||||
saveConfig({
|
||||
variables: { config: { receiptPrinting: { active: it } } }
|
||||
})
|
||||
}
|
||||
/>
|
||||
<BooleanPropertiesTable
|
||||
title={'Visible on the receipt (optionals)'}
|
||||
disabled={receiptPrintingConfig.active === 'off'}
|
||||
data={receiptPrintingConfig}
|
||||
elements={[
|
||||
// {
|
||||
// name: 'logo',
|
||||
// display: (
|
||||
// <>
|
||||
// {'Logo'}
|
||||
// <ActionButton
|
||||
// className={classes.actionButton}
|
||||
// Icon={UploadIcon}
|
||||
// InverseIcon={UploadIconInverse}
|
||||
// color={'primary'}
|
||||
// onClick={() => {
|
||||
// // TODO: make the replace logo feature
|
||||
// }}>
|
||||
// Replace logo
|
||||
// </ActionButton>
|
||||
// </>
|
||||
// ),
|
||||
// value: receiptPrintingConfig.logo
|
||||
// },
|
||||
{
|
||||
name: 'operatorWebsite',
|
||||
display: 'Operator website',
|
||||
value: receiptPrintingConfig.operatorWebsite
|
||||
},
|
||||
{
|
||||
name: 'operatorEmail',
|
||||
display: 'Operator email',
|
||||
value: receiptPrintingConfig.operatorEmail
|
||||
},
|
||||
{
|
||||
name: 'operatorPhone',
|
||||
display: 'Operator phone',
|
||||
value: receiptPrintingConfig.operatorPhone
|
||||
},
|
||||
{
|
||||
name: 'companyRegistration',
|
||||
display: 'Company registration',
|
||||
value: receiptPrintingConfig.companyRegistration
|
||||
},
|
||||
{
|
||||
name: 'machineLocation',
|
||||
display: 'Machine location',
|
||||
value: receiptPrintingConfig.machineLocation
|
||||
},
|
||||
{
|
||||
name: 'customerNameOrPhoneNumber',
|
||||
display: 'Customer name or phone number (if known)',
|
||||
value: receiptPrintingConfig.customerNameOrPhoneNumber
|
||||
},
|
||||
// {
|
||||
// name: 'commission',
|
||||
// display: 'Commission',
|
||||
// value: receiptPrintingConfig.commission
|
||||
// },
|
||||
{
|
||||
name: 'exchangeRate',
|
||||
display: 'Exchange rate',
|
||||
value: receiptPrintingConfig.exchangeRate
|
||||
},
|
||||
{
|
||||
name: 'addressQRCode',
|
||||
display: 'Address QR code',
|
||||
value: receiptPrintingConfig.addressQRCode
|
||||
}
|
||||
// {
|
||||
// name: 'customText',
|
||||
// display: 'Custom text',
|
||||
// value: receiptPrintingConfig.customText
|
||||
// }
|
||||
]}
|
||||
save={save}
|
||||
/>
|
||||
{/* TODO: textInput should appear only when table is in edit mode, and have it's value saved along with the table values */}
|
||||
{/* <TextInput
|
||||
className={classes.textInput}
|
||||
label={'Custom text content'}
|
||||
multiline
|
||||
rows="4"
|
||||
defaultValue={receiptPrintingConfig.customTextContent}
|
||||
/> */}
|
||||
{/* TODO: add receipt preview on the right side of the page */}
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
export default ReceiptPrinting
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
const mainStyles = {
|
||||
textInput: {
|
||||
margin: [[28, 20]],
|
||||
width: 304
|
||||
},
|
||||
actionButton: {
|
||||
margin: [[0, 24]]
|
||||
}
|
||||
}
|
||||
|
||||
export { mainStyles }
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import ReceiptPrinting from './ReceiptPrinting'
|
||||
|
||||
export default ReceiptPrinting
|
||||
Loading…
Add table
Add a link
Reference in a new issue