import { FC, ChangeEvent, useState, useEffect } from "react"
import {
Button,
Grid,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
useMediaQuery,
OutlinedInput,
FormControl,
InputLabel,
InputAdornment,
IconButton,
Tooltip,
} from "@material-ui/core"
import useStyles from "./styles"
import { useTheme } from "@material-ui/core/styles"
import DeleteIcon from "@material-ui/icons/Delete"
import { useSelector, useDispatch } from "react-redux"
import { RootState } from "../../redux/store"
import { editCredential } from "../../redux/actions/credentialActions"
import { translate } from "../../lang"
import { AccessCredentialPropT, CredentialPropValueT, ReduxCredentialT } from "../../misc/types"
type Props = {
codes: string[]
option: 1 | 2
isCrypto: boolean
}
type Baggage = {
oldCredential: ReduxCredentialT
prop: AccessCredentialPropT
newValue: CredentialPropValueT
}
/**
* @alias EditCodes
*
* @description This is the component responsible of managing the multiple codes property of a credential, receives the codes as an array, but here is the logic to update the codes on the global state.
*
* @property {string[]} codes The codes that will be rendered & dispatched to redux
*
* @property {1 | 2} option The layout for the codes (1: shows a button which opens a model. 2: shows every code inside an input)
*
* @property {boolean} isCrypto If the codes to edit are the words to access crypto currency wallets
*
* @example
* <EditCodes codes={["", ""]} option={1} isCrypto />
*/
const EditCodes: FC<Props> = ({ codes, option, isCrypto }) => {
const theme = useTheme()
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"))
const classes = useStyles()
const { lng } = useSelector((state: RootState) => state.lng)
const { credential } = useSelector((state: RootState) => state.credential)
const dispatch = useDispatch()
const [open, setOpen] = useState(false)
const [editingCodes, setEditingCodes] = useState<string[]>(codes)
const handleClickOpen = () => {
setOpen(true)
}
const handleClose = () => {
setOpen(false)
}
const removeCode = (code: string) => {
const editedArray: string[] = []
editingCodes.forEach((codeValue) => {
if (codeValue !== code) {
editedArray.push(codeValue)
}
})
setEditingCodes(editedArray)
}
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const newArray = option === 1 ? [...codes] : [...editingCodes]
const index = Number(e.target.id.substring(5))
newArray[index] = e.target.value
setEditingCodes(newArray)
}
useEffect(() => {
let baggage: Baggage = {
oldCredential: credential,
newValue: editingCodes,
prop: "multiple_codes",
}
if (isCrypto) {
baggage.prop = "crypto_codes"
}
dispatch(editCredential(baggage))
}, [editingCodes])
if (option === 1) {
return (
<>
<Grid item xs={12} className={classes.textCenter}>
<Button
size="large"
color="primary"
variant="contained"
disableElevation
onClick={handleClickOpen}
data-testid="test_open_modal"
>
{translate("edit_codes", lng)}
</Button>
</Grid>
<Dialog
fullScreen={fullScreen}
open={open}
onClose={handleClose}
aria-labelledby="edit-dialog"
scroll="paper"
data-testid="test_modal"
>
<DialogTitle id="edit-dialog">{translate("edit_codes", lng)}</DialogTitle>
<DialogContent>
<Grid container justify="space-around" spacing={4}>
{codes.map((code: string, index: number) => (
<Grid key={index} item xs={12} md={6}>
<FormControl variant="outlined" fullWidth>
<InputLabel>{index + 1}</InputLabel>
<OutlinedInput
id={`${isCrypto ? "word" : "code"}-${index}`}
label={`${index + 1}`}
value={code}
onChange={handleChange}
endAdornment={
<InputAdornment position="end">
<Tooltip
title={translate("delete", lng)}
placement="top"
>
<IconButton
aria-label={translate(
"edit_codes",
lng,
2
)}
onClick={() => removeCode(code)}
>
<DeleteIcon />
</IconButton>
</Tooltip>
</InputAdornment>
}
inputProps={{
"data-testid": `test_${index}`,
}}
/>
</FormControl>
</Grid>
))}
<Grid item xs={12} className={classes.textCenter}>
<Button
variant="outlined"
color="primary"
onClick={() => setEditingCodes([...codes, ""])}
>
{translate("edit_codes", lng, 1)}
</Button>
</Grid>
</Grid>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="default">
{translate("go_back", lng)}
</Button>
<Button onClick={handleClose} color="primary">
{translate("access_management", lng, 2)}
</Button>
</DialogActions>
</Dialog>
</>
)
} else {
return (
<>
<Grid container justify="space-around" spacing={4} data-testid="test_edit_codes">
{editingCodes.map((code: string, index: number) => (
<Grid key={index} item xs={12} md={6}>
<FormControl variant="outlined" fullWidth>
<InputLabel>{index + 1}</InputLabel>
<OutlinedInput
id={`${isCrypto ? "word" : "code"}-${index}`}
label={`${index + 1}`}
value={code}
onChange={handleChange}
endAdornment={
<InputAdornment position="end">
<Tooltip
title={translate("delete", lng)}
placement="top"
>
<IconButton
aria-label={translate("edit_codes", lng, 2)}
onClick={() => removeCode(code)}
>
<DeleteIcon />
</IconButton>
</Tooltip>
</InputAdornment>
}
inputProps={{
"data-testid": `test_${index}`,
}}
/>
</FormControl>
</Grid>
))}
<Grid item xs={12} className={classes.textCenter}>
<Button
variant="outlined"
color="primary"
onClick={() => setEditingCodes([...editingCodes, ""])}
>
{translate("edit_codes", lng, 1)}
</Button>
</Grid>
</Grid>
</>
)
}
}
export default EditCodes