robosats/frontend/src/components/AutocompletePayments.js

335 lines
8.7 KiB
JavaScript
Raw Normal View History

2022-09-09 17:18:04 +00:00
import React, { useState } from 'react';
import PropTypes from 'prop-types';
2022-04-17 19:14:22 +00:00
import { useTranslation } from 'react-i18next';
import { useAutocomplete } from '@mui/base/AutocompleteUnstyled';
import { styled } from '@mui/material/styles';
2022-09-09 17:18:04 +00:00
import { Button, Tooltip } from '@mui/material';
import { paymentMethods, swapDestinations } from './payment-methods/Methods';
2022-04-01 14:52:44 +00:00
2022-05-08 15:43:08 +00:00
// Icons
import DashboardCustomizeIcon from '@mui/icons-material/DashboardCustomize';
2022-04-01 14:52:44 +00:00
import AddIcon from '@mui/icons-material/Add';
2022-09-09 17:18:04 +00:00
import PaymentIcon from './payment-methods/Icons';
2022-05-08 15:43:08 +00:00
import CheckIcon from '@mui/icons-material/Check';
import CloseIcon from '@mui/icons-material/Close';
const Root = styled('div')(
({ theme }) => `
2022-09-09 17:18:04 +00:00
color: ${theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.65)' : 'rgba(0,0,0,.85)'};
font-size: 14px;
`,
);
const Label = styled('label')(
2022-09-09 17:18:04 +00:00
({ theme, error }) => `
color: ${
theme.palette.mode === 'dark' ? (error ? '#f44336' : '#cfcfcf') : error ? '#dd0000' : '#717171'
};
align: center;
padding: 0 0 4px;
line-height: 1.5; f44336
display: block;
font-size: 13px;
`,
);
const InputWrapper = styled('div')(
2022-09-09 17:18:04 +00:00
({ theme, error }) => `
width: 244px;
min-height: 44px;
max-height: 124px;
2022-09-09 17:18:04 +00:00
border: 1px solid ${
theme.palette.mode === 'dark' ? (error ? '#f44336' : '#434343') : error ? '#dd0000' : '#c4c4c4'
};
background-color: ${theme.palette.mode === 'dark' ? '#141414' : '#fff'};
border-radius: 4px;
padding: 1px;
display: flex;
flex-wrap: wrap;
overflow-y:auto;
2022-05-02 19:28:34 +00:00
&:hover {
2022-09-09 17:18:04 +00:00
border-color: ${
theme.palette.mode === 'dark'
? error
? '#f44336'
: '#ffffff'
: error
? '#dd0000'
: '#2f2f2f'
};
}
&.focused {
2022-09-09 17:18:04 +00:00
border: 2px solid ${
theme.palette.mode === 'dark'
? error
? '#f44336'
: '#90caf9'
: error
? '#dd0000'
: '#1976d2'
};
}
& input {
background-color: ${theme.palette.mode === 'dark' ? '#141414' : '#fff'};
2022-09-09 17:18:04 +00:00
color: ${theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.65)' : 'rgba(0,0,0,.85)'};
height: 30px;
box-sizing: border-box;
padding: 4px 6px;
width: 0;
min-width: 30px;
font-size: 15px;
flex-grow: 1;
border: 0;
margin: 0;
outline: 0;
max-height: 124px;
}
`,
);
function Tag(props) {
const { label, icon, onDelete, ...other } = props;
return (
<div {...other}>
2022-09-09 17:18:04 +00:00
<div style={{ position: 'relative', left: '-5px', top: '4px' }}>
<PaymentIcon width={22} height={22} icon={icon} />
</div>
<span style={{ position: 'relative', left: '2px' }}>{label}</span>
<CloseIcon onClick={onDelete} />
</div>
);
}
Tag.propTypes = {
label: PropTypes.string.isRequired,
icon: PropTypes.string.isRequired,
onDelete: PropTypes.func.isRequired,
};
const StyledTag = styled(Tag)(
({ theme }) => `
display: flex;
align-items: center;
height: 34px;
margin: 2px;
line-height: 22px;
2022-09-09 17:18:04 +00:00
background-color: ${theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.08)' : '#fafafa'};
border: 1px solid ${theme.palette.mode === 'dark' ? '#303030' : '#e8e8e8'};
border-radius: 2px;
box-sizing: content-box;
padding: 0 4px 0 10px;
outline: 0;
overflow: hidden;
&:focus {
border-color: ${theme.palette.mode === 'dark' ? '#177ddc' : '#40a9ff'};
background-color: ${theme.palette.mode === 'dark' ? '#003b57' : '#e6f7ff'};
}
& span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 15px;
}
& svg {
font-size: 15px;
cursor: pointer;
padding: 4px;
}
`,
);
const ListHeader = styled('span')(
2022-09-09 17:18:04 +00:00
({ theme }) => `
color: ${theme.palette.mode === 'dark' ? '#90caf9' : '#1976d2'};
Spanish translation (#96) * Translate tp Spanish (#93) * update_es.json * Update es.json Translate eng to esp from line 222 to end Co-authored-by: mamifiero <99733022+mamifiero@users.noreply.github.com> * Fit book and maker UI for variable length text * Correction and style of the Spanish translation (#95) * Correction and style of the Spanish translation The following terms have been unified and adjusted only in Spanish, but can be done in English base too: * Satoshis, satoshis, sats = Sats (in honour of RoboSats) * Robot (always first capital letter in honour of RoboSats) * Lightning, lightning, LN, Lightning Network = Lightningç * Telegram, TG = Telegram * Trade, Swap = Trade (Intercambio) * Trade counterpart, Peer, Trading peer = Peer (Compañero) * Hold invoice, Bond & Fidelity Bond = Bond (Fianza) * Trade collateral, Collateral, Trade escrow, Escrow = Collateral (Colateral) * Burner contact method, Burner email = Burner contact method (Método de contacto de usar y tirar) * Hidden service (deprecated), Onion services, .onion site = Onion site (sitio cebolla) https://tb-manual.torproject.org/es/onion-services/ * Tor Browser (Navegador Tor) https://tb-manual.torproject.org/es/about/ * Craiglist is not common on spanish countries, so now inserted WallaPop * Update es.json Co-authored-by: decentralized.b <58108487+decentralizedb@users.noreply.github.com> Co-authored-by: mamifiero <99733022+mamifiero@users.noreply.github.com> Co-authored-by: ibertario <68381662+ibertario@users.noreply.github.com>
2022-04-15 16:15:57 +00:00
align: left;
line-height:10px;
max-height: 10px;
display: inline-block;
background-color: ${theme.palette.mode === 'dark' ? '#141414' : '#ffffff'};
font-size: 12px;
pointer-events: none;
`,
);
const Listbox = styled('ul')(
({ theme }) => `
width: 244px;
margin: 2px 0 0;
padding: 0;
position: absolute;
list-style: none;
background-color: ${theme.palette.mode === 'dark' ? '#141414' : '#fff'};
overflow: auto;
max-height: 250px;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
z-index: 999;
& li {
padding: 5px 12px;
display: flex;
& span {
flex-grow: 1;
}
& svg {
color: transparent;
}
2022-04-01 14:52:44 +00:00
}
& li[aria-selected='true'] {
background-color: ${theme.palette.mode === 'dark' ? '#2b2b2b' : '#fafafa'};
font-weight: 600;
& svg {
2022-04-01 14:52:44 +00:00
color: ${theme.palette.primary.main};
}
}
& li[data-focus='true'] {
background-color: ${theme.palette.mode === 'dark' ? '#003b57' : '#e6f7ff'};
cursor: pointer;
& svg {
color: currentColor;
}
}
`,
);
export default function AutocompletePayments(props) {
2022-05-08 15:43:08 +00:00
const { t } = useTranslation();
const {
getRootProps,
getInputLabelProps,
getInputProps,
getTagProps,
getListboxProps,
getOptionProps,
groupedOptions,
value,
2022-09-09 17:18:04 +00:00
focused = 'true',
setAnchorEl,
} = useAutocomplete({
2022-09-09 17:18:04 +00:00
sx: { width: '200px', align: 'left' },
id: 'payment-methods',
multiple: true,
2022-09-09 17:18:04 +00:00
options: props.optionsType == 'fiat' ? paymentMethods : swapDestinations,
getOptionLabel: (option) => option.name,
2022-09-09 17:18:04 +00:00
onInputChange: (e) => setVal(e ? (e.target.value ? e.target.value : '') : ''),
onChange: (event, value) => props.onAutocompleteChange(optionsToString(value)),
2022-09-09 17:18:04 +00:00
onClose: () => setVal(() => ''),
});
const [val, setVal] = useState();
2022-09-09 17:18:04 +00:00
function optionsToString(newValue) {
let str = '';
const arrayLength = newValue.length;
for (let i = 0; i < arrayLength; i++) {
2022-09-09 17:18:04 +00:00
str += newValue[i].name + ' ';
}
return str.slice(0, -1);
}
2022-09-09 17:18:04 +00:00
function handleAddNew(inputProps) {
paymentMethods.push({ name: inputProps.value, icon: 'custom' });
const a = value.push({ name: inputProps.value, icon: 'custom' });
2022-09-09 17:18:04 +00:00
setVal(() => '');
2022-09-09 17:18:04 +00:00
if (a || a == null) {
props.onAutocompleteChange(optionsToString(value));
}
return false;
}
2022-05-02 19:28:34 +00:00
return (
<Root>
2022-09-09 17:18:04 +00:00
<div style={{ height: '5px' }}></div>
<Tooltip
placement='top'
enterTouchDelay={300}
enterDelay={700}
enterNextDelay={2000}
title={props.tooltipTitle}
>
<div {...getRootProps()}>
<Label {...getInputLabelProps()} error={props.error ? 'error' : null}>
{' '}
{props.label}
</Label>
<InputWrapper
ref={setAnchorEl}
error={props.error ? 'error' : null}
className={focused ? 'focused' : ''}
>
2022-05-10 18:44:12 +00:00
{value.map((option, index) => (
<StyledTag label={t(option.name)} icon={option.icon} {...getTagProps({ index })} />
))}
<input {...getInputProps()} value={val || ''} />
2022-05-10 18:44:12 +00:00
</InputWrapper>
</div>
</Tooltip>
{groupedOptions.length > 0 ? (
<Listbox {...getListboxProps()}>
2022-09-09 17:18:04 +00:00
<div
style={{
position: 'fixed',
minHeight: '20px',
marginLeft: 120 - props.listHeaderText.length * 3,
marginTop: '-13px',
}}
>
<ListHeader>
<i>{props.listHeaderText + ''} </i>{' '}
</ListHeader>
</div>
{groupedOptions.map((option, index) => (
2022-05-02 19:28:34 +00:00
<li key={option.name} {...getOptionProps({ option, index })}>
2022-09-09 17:18:04 +00:00
<Button
fullWidth={true}
color='inherit'
size='small'
sx={{ textTransform: 'none' }}
style={{ justifyContent: 'flex-start' }}
>
<div style={{ position: 'relative', right: '4px', top: '4px' }}>
<AddIcon style={{ color: '#1976d2' }} sx={{ width: 18, height: 18 }} />
</div>
{t(option.name)}
2022-04-01 14:52:44 +00:00
</Button>
2022-09-09 17:18:04 +00:00
<div style={{ position: 'relative', top: '5px' }}>
<CheckIcon />
</div>
</li>
))}
2022-09-09 17:18:04 +00:00
{val != null ? (
val.length > 2 ? (
<Button size='small' fullWidth={true} onClick={() => handleAddNew(getInputProps())}>
<DashboardCustomizeIcon sx={{ width: 18, height: 18 }} />
{props.addNewButtonText}
</Button>
) : null
) : null}
</Listbox>
) : // Here goes what happens if there is no groupedOptions
2022-09-09 17:18:04 +00:00
getInputProps().value.length > 0 ? (
<Listbox {...getListboxProps()}>
2022-09-09 17:18:04 +00:00
<Button fullWidth={true} onClick={() => handleAddNew(getInputProps())}>
<DashboardCustomizeIcon sx={{ width: 20, height: 20 }} />
{props.addNewButtonText}
</Button>
</Listbox>
2022-09-09 17:18:04 +00:00
) : null}
</Root>
);
2022-09-09 17:18:04 +00:00
}