robosats/frontend/src/components/MakerForm/AutocompletePayments.tsx

418 lines
11 KiB
TypeScript
Raw Normal View History

2022-09-09 17:18:04 +00:00
import React, { useState } from 'react';
2022-04-17 19:14:22 +00:00
import { useTranslation } from 'react-i18next';
2023-03-03 15:25:21 +00:00
import useAutocomplete from '@mui/base/useAutocomplete';
import { styled } from '@mui/material/styles';
import {
Button,
Fade,
Tooltip,
Typography,
Grow,
useTheme,
type SxProps,
type Theme,
} from '@mui/material';
Refactor and Init RoboSats PRO (#296) commit 9c6d55cfc77d42471da3e865f2729167597868e5 Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Thu Oct 20 10:35:49 2022 -0700 Small fixes commit 23d6c00ccb5e78593e768c36b866d02f26031e7b Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Thu Oct 20 06:12:42 2022 -0700 Refactor frontend commit b2c21d4a98c49f6168bc3ff6e6a3d7b9f8943a12 Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Wed Oct 19 07:26:00 2022 -0700 Small fixes (more) commit 78a8ab799dc33e8f8b8f14e22e155bbc7104c3a9 Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Wed Oct 19 02:11:03 2022 -0700 Try out to revert depth chart commit ef73c980a8cfc4ae760e720e3bca99acc30b7270 Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Tue Oct 18 11:43:37 2022 -0700 Small fixes commit fa3e60208f8f292256dd90813e7beff15db3057a Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Tue Oct 18 09:43:03 2022 -0700 Add old UserGen and BottomBar to new main.tsx commit 1e257d1924df20e2fa4feb7f6afce4f31f2a9acc Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Tue Oct 18 04:01:53 2022 -0700 Add Maker and Book page to new main.tsx commit 037d46ceef34df09530e645a2e01c9fbd9b3efd4 Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Mon Oct 17 08:54:55 2022 -0700 Add Main component WIP commit e43b274c33a75ab5050be360a3d01f655e1e8142 Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Mon Oct 17 04:32:43 2022 -0700 App as functional component
2022-10-20 18:06:16 +00:00
import { fiatMethods, swapMethods, PaymentIcon } from '../PaymentMethods';
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-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 }) => `
color: ${theme.palette.text.primary};
font-size: ${theme.typography.fontSize};
`,
);
const Label = styled('label')(
({ theme, error, sx }) => `
2022-09-09 17:18:04 +00:00
color: ${
theme.palette.mode === 'dark'
? error === true
? '#f44336'
: '#cfcfcf'
: error === true
? '#dd0000'
: '#717171'
2022-09-09 17:18:04 +00:00
};
pointer-events: none;
position: relative;
left: 1em;
top: ${String(sx.top) ?? '0.72em'};
maxHeight: 0em;
height: 0em;
white-space: no-wrap;
font-size: 1em;
`,
);
const InputWrapper = styled('div')(
({ theme, error, sx }) => `
min-height: ${String(sx.minHeight)};
max-height: ${String(sx.maxHeight)};
2022-09-09 17:18:04 +00:00
border: 1px solid ${
theme.palette.mode === 'dark'
? error === ''
? '#f44336'
: '#434343'
: error === ''
? '#dd0000'
: '#c4c4c4'
2022-09-09 17:18:04 +00:00
};
background-color: ${theme.palette.mode === 'dark' ? '#141414' : '#fff'};
border-radius: 4px;
border-color: ${sx.borderColor !== undefined ? `border-color ${String(sx.borderColor)}` : ''}
padding: 1px;
display: flex;
flex-wrap: wrap;
overflow-y:auto;
align-items: center;
2022-05-02 19:28:34 +00:00
&:hover {
2022-09-09 17:18:04 +00:00
border-color: ${
theme.palette.mode === 'dark'
? error === true
2022-09-09 17:18:04 +00:00
? '#f44336'
: String(sx.hoverBorderColor)
: error === true
? '#dd0000'
: '#2f2f2f'
2022-09-09 17:18:04 +00:00
};
}
&.focused {
2022-09-09 17:18:04 +00:00
border: 2px solid ${
theme.palette.mode === 'dark'
? error === true
2022-09-09 17:18:04 +00:00
? '#f44336'
: '#90caf9'
: error === true
? '#dd0000'
: '#1976d2'
2022-09-09 17:18:04 +00:00
};
}
& 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: 2em;
box-sizing: border-box;
padding: 0.28em 0.4em;
width: 0;
min-width: 2.15em;
font-size: ${theme.typography.fontSize * 1.0714};
flex-grow: 1;
border: 0;
margin: 0;
outline: 0;
max-height: 8.6em;
}
`,
);
2023-03-03 15:25:21 +00:00
interface TagProps {
label: string;
icon: string;
onDelete: () => void;
2023-10-12 12:57:51 +00:00
onClick: () => void;
2023-03-03 15:25:21 +00:00
}
const Tag: React.FC<TagProps> = ({ label, icon, onDelete, onClick, ...other }) => {
const theme = useTheme();
const iconSize = 1.5 * theme.typography.fontSize;
return (
<div {...other}>
2023-10-12 12:57:51 +00:00
<div style={{ position: 'relative', left: '-5px', top: '0.28em' }} onClick={onClick}>
<PaymentIcon width={iconSize} height={iconSize} icon={icon} />
2022-09-09 17:18:04 +00:00
</div>
2023-10-12 12:57:51 +00:00
<span style={{ position: 'relative', left: '2px' }} onClick={onClick}>
{label}
</span>
<CloseIcon onClick={onDelete} />
</div>
);
};
const StyledTag = styled(Tag)(
({ theme, sx }) => `
display: flex;
align-items: center;
height: ${String(sx?.height ?? '2.1em')};
margin: 2px;
line-height: 1.5em;
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 0.28em 0 0.65em;
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: 0.928em;
}
& svg {
font-size: 0.857em;
cursor: pointer;
padding: 0.28em;
}
`,
);
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:0.7em;
max-height: 10.7em;
display: inline-block;
background-color: ${theme.palette.mode === 'dark' ? '#141414' : '#ffffff'};
font-size: 0.875em;
pointer-events: none;
`,
);
const Listbox = styled('ul')(
({ theme, sx }) => `
width: ${String(sx?.width ?? '15.6em')};
margin: 2px 0 0;
padding: 0;
position: absolute;
list-style: none;
background-color: ${theme.palette.mode === 'dark' ? '#141414' : '#fff'};
overflow: auto;
max-height: 17em;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
z-index: 999;
& li {
padding: 0em 0em;
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;
}
}
`,
);
interface AutocompletePaymentsProps {
value: string;
optionsType: 'fiat' | 'swap';
onAutocompleteChange: (value: string) => void;
tooltipTitle: string;
labelProps: any;
tagProps: any;
listBoxProps: any;
error: string;
label: string;
sx: SxProps<Theme>;
addNewButtonText: string;
isFilter: boolean;
listHeaderText: string;
}
const AutocompletePayments: React.FC<AutocompletePaymentsProps> = (props) => {
2022-05-08 15:43:08 +00:00
const { t } = useTranslation();
const {
getRootProps,
getInputLabelProps,
getInputProps,
getTagProps,
getListboxProps,
getOptionProps,
groupedOptions,
value,
focused = true,
setAnchorEl,
} = useAutocomplete({
fullWidth: true,
id: 'payment-methods',
multiple: true,
value: props.value,
options: props.optionsType === 'fiat' ? fiatMethods : swapMethods,
getOptionLabel: (option) => option.name,
onInputChange: (e) => {
setVal(e.target.value ?? '');
},
onChange: (event, value) => {
props.onAutocompleteChange(value);
},
onClose: () => {
setVal(() => '');
},
});
const [val, setVal] = useState('');
const fewerOptions = groupedOptions.length > 8 ? groupedOptions.slice(0, 8) : groupedOptions;
const theme = useTheme();
const iconSize = 1.5 * theme.typography.fontSize;
function handleAddNew(inputProps: any): void {
Refactor and Init RoboSats PRO (#296) commit 9c6d55cfc77d42471da3e865f2729167597868e5 Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Thu Oct 20 10:35:49 2022 -0700 Small fixes commit 23d6c00ccb5e78593e768c36b866d02f26031e7b Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Thu Oct 20 06:12:42 2022 -0700 Refactor frontend commit b2c21d4a98c49f6168bc3ff6e6a3d7b9f8943a12 Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Wed Oct 19 07:26:00 2022 -0700 Small fixes (more) commit 78a8ab799dc33e8f8b8f14e22e155bbc7104c3a9 Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Wed Oct 19 02:11:03 2022 -0700 Try out to revert depth chart commit ef73c980a8cfc4ae760e720e3bca99acc30b7270 Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Tue Oct 18 11:43:37 2022 -0700 Small fixes commit fa3e60208f8f292256dd90813e7beff15db3057a Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Tue Oct 18 09:43:03 2022 -0700 Add old UserGen and BottomBar to new main.tsx commit 1e257d1924df20e2fa4feb7f6afce4f31f2a9acc Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Tue Oct 18 04:01:53 2022 -0700 Add Maker and Book page to new main.tsx commit 037d46ceef34df09530e645a2e01c9fbd9b3efd4 Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Mon Oct 17 08:54:55 2022 -0700 Add Main component WIP commit e43b274c33a75ab5050be360a3d01f655e1e8142 Author: Reckless_Satoshi <reckless.satoshi@protonmail.com> Date: Mon Oct 17 04:32:43 2022 -0700 App as functional component
2022-10-20 18:06:16 +00:00
fiatMethods.push({ name: inputProps.value, icon: 'custom' });
const a = value.push({ name: inputProps.value, icon: 'custom' });
2022-09-09 17:18:04 +00:00
setVal(() => '');
if (a !== undefined) {
props.onAutocompleteChange(value);
2022-09-09 17:18:04 +00:00
}
}
2022-05-02 19:28:34 +00:00
return (
<Root>
2022-09-09 17:18:04 +00:00
<Tooltip
placement='top'
enterTouchDelay={props.tooltipTitle === '' ? 99999 : 300}
enterDelay={props.tooltipTitle === '' ? 99999 : 700}
2022-09-09 17:18:04 +00:00
enterNextDelay={2000}
title={props.tooltipTitle}
>
<div {...getRootProps()}>
<Fade
appear={false}
in={fewerOptions.length === 0 && value.length === 0 && val.length === 0}
>
<div style={{ height: 0, display: 'flex', alignItems: 'flex-start' }}>
<Label
{...getInputLabelProps()}
sx={{ top: '0.72em', ...(props.labelProps?.sx ?? {}) }}
error={Boolean(props.error)}
>
{props.label}
</Label>
</div>
</Fade>
2022-09-09 17:18:04 +00:00
<InputWrapper
ref={setAnchorEl}
error={Boolean(props.error)}
2022-09-09 17:18:04 +00:00
className={focused ? 'focused' : ''}
sx={{
minHeight: '2.9em',
maxHeight: '8.6em',
hoverBorderColor: '#ffffff',
...props.sx,
}}
2022-09-09 17:18:04 +00:00
>
2022-05-10 18:44:12 +00:00
{value.map((option, index) => (
<StyledTag
key={index}
label={t(option.name)}
icon={option.icon}
2023-10-12 12:57:51 +00:00
onClick={props.onClick}
sx={{ height: '2.1em', ...(props.tagProps ?? {}) }}
{...getTagProps({ index })}
/>
2022-05-10 18:44:12 +00:00
))}
{value.length > 0 && props.isFilter ? null : <input {...getInputProps()} value={val} />}
2022-05-10 18:44:12 +00:00
</InputWrapper>
</div>
</Tooltip>
<Grow in={fewerOptions.length > 0}>
<Listbox sx={props.listBoxProps?.sx ?? undefined} {...getListboxProps()}>
{!props.isFilter ? (
<div
style={{
position: 'fixed',
minHeight: '1.428em',
marginLeft: `${3 - props.listHeaderText.length * 0.05}em`,
marginTop: '-0.928em',
}}
>
<ListHeader>
<i>{props.listHeaderText + ''} </i>{' '}
</ListHeader>
</div>
) : null}
{fewerOptions.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={{ padding: '0.286em', position: 'relative', top: '0.35em' }}>
<PaymentIcon width={iconSize} height={iconSize} icon={option.icon} />
2022-09-09 17:18:04 +00:00
</div>
<Typography variant='inherit' align='left'>
{t(option.name)}
</Typography>
2022-04-01 14:52:44 +00:00
</Button>
<div style={{ position: 'relative', top: '0.357em' }}>
2022-09-09 17:18:04 +00:00
<CheckIcon />
</div>
</li>
))}
{val != null || !props.isFilter ? (
2022-09-09 17:18:04 +00:00
val.length > 2 ? (
<Button
size='small'
fullWidth={true}
onClick={() => {
handleAddNew(getInputProps());
}}
>
<DashboardCustomizeIcon sx={{ width: '1em', height: '1em' }} />
2022-09-09 17:18:04 +00:00
{props.addNewButtonText}
</Button>
) : null
) : null}
</Listbox>
</Grow>
{/* Here goes what happens if there is no fewerOptions */}
<Grow in={getInputProps().value.length > 0 && !props.isFilter && fewerOptions.length === 0}>
<Listbox {...getListboxProps()}>
<Button
fullWidth={true}
onClick={() => {
handleAddNew(getInputProps());
}}
>
<DashboardCustomizeIcon sx={{ width: '1.28em', height: '1.28em' }} />
2022-09-09 17:18:04 +00:00
{props.addNewButtonText}
</Button>
</Listbox>
</Grow>
</Root>
);
};
export default AutocompletePayments;