mirror of
https://github.com/RoboSats/robosats.git
synced 2025-07-18 16:53:16 +00:00

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
356 lines
9.8 KiB
JavaScript
356 lines
9.8 KiB
JavaScript
import React, { useState } from 'react';
|
||
import PropTypes from 'prop-types';
|
||
import { useTranslation } from 'react-i18next';
|
||
import { useAutocomplete } from '@mui/base/AutocompleteUnstyled';
|
||
import { styled } from '@mui/material/styles';
|
||
import { Button, Fade, Tooltip, Typography, Grow } from '@mui/material';
|
||
import { fiatMethods, swapMethods, PaymentIcon } from '../PaymentMethods';
|
||
|
||
// Icons
|
||
import DashboardCustomizeIcon from '@mui/icons-material/DashboardCustomize';
|
||
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 }) => `
|
||
color: ${
|
||
theme.palette.mode === 'dark' ? (error ? '#f44336' : '#cfcfcf') : error ? '#dd0000' : '#717171'
|
||
};
|
||
pointer-events: none;
|
||
position: relative;
|
||
left: 1em;
|
||
top: ${sx.top};
|
||
maxHeight: 0em;
|
||
height: 0em;
|
||
white-space: no-wrap;
|
||
font-size: 1em;
|
||
`,
|
||
);
|
||
|
||
const InputWrapper = styled('div')(
|
||
({ theme, error, sx }) => `
|
||
min-height: ${sx.minHeight};
|
||
max-height: ${sx.maxHeight};
|
||
border: 1px solid ${
|
||
theme.palette.mode === 'dark' ? (error ? '#f44336' : '#434343') : error ? '#dd0000' : '#c4c4c4'
|
||
};
|
||
background-color: ${theme.palette.mode === 'dark' ? '#141414' : '#fff'};
|
||
border-radius: 4px;
|
||
border-color: ${sx.borderColor ? `border-color ${sx.borderColor}` : ''}
|
||
padding: 1px;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
overflow-y:auto;
|
||
align-items: center;
|
||
|
||
&:hover {
|
||
border-color: ${
|
||
theme.palette.mode === 'dark'
|
||
? error
|
||
? '#f44336'
|
||
: sx.hoverBorderColor
|
||
: error
|
||
? '#dd0000'
|
||
: '#2f2f2f'
|
||
};
|
||
}
|
||
|
||
&.focused {
|
||
border: 2px solid ${
|
||
theme.palette.mode === 'dark'
|
||
? error
|
||
? '#f44336'
|
||
: '#90caf9'
|
||
: error
|
||
? '#dd0000'
|
||
: '#1976d2'
|
||
};
|
||
}
|
||
|
||
& input {
|
||
background-color: ${theme.palette.mode === 'dark' ? '#141414' : '#fff'};
|
||
color: ${theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.65)' : 'rgba(0,0,0,.85)'};
|
||
height: 2.15em;
|
||
box-sizing: border-box;
|
||
padding: 4px 6px;
|
||
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;
|
||
}
|
||
`,
|
||
);
|
||
|
||
function Tag(props) {
|
||
const { label, icon, onDelete, ...other } = props;
|
||
return (
|
||
<div {...other}>
|
||
<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, sx }) => `
|
||
display: flex;
|
||
align-items: center;
|
||
height: ${sx.height};
|
||
margin: 2px;
|
||
line-height: 1.5em;
|
||
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: 0.928em;
|
||
}
|
||
|
||
& svg {
|
||
font-size: 0.857em;
|
||
cursor: pointer;
|
||
padding: 4px;
|
||
}
|
||
`,
|
||
);
|
||
|
||
const ListHeader = styled('span')(
|
||
({ theme }) => `
|
||
color: ${theme.palette.mode === 'dark' ? '#90caf9' : '#1976d2'};
|
||
align: left;
|
||
line-height:10px;
|
||
max-height: 10px;
|
||
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: ${sx ? 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;
|
||
}
|
||
|
||
}
|
||
|
||
& li[aria-selected='true'] {
|
||
background-color: ${theme.palette.mode === 'dark' ? '#2b2b2b' : '#fafafa'};
|
||
font-weight: 600;
|
||
|
||
& svg {
|
||
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) {
|
||
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 ? (e.target.value ? 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;
|
||
|
||
function handleAddNew(inputProps) {
|
||
fiatMethods.push({ name: inputProps.value, icon: 'custom' });
|
||
const a = value.push({ name: inputProps.value, icon: 'custom' });
|
||
setVal(() => '');
|
||
|
||
if (a || a == null) {
|
||
props.onAutocompleteChange(value);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
return (
|
||
<Root>
|
||
<Tooltip
|
||
placement='top'
|
||
enterTouchDelay={props.tooltipTitle == '' ? 99999 : 300}
|
||
enterDelay={props.tooltipTitle == '' ? 99999 : 700}
|
||
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 ? props.labelProps.sx : {}) }}
|
||
error={props.error ? 'error' : null}
|
||
>
|
||
{props.label}
|
||
</Label>
|
||
</div>
|
||
</Fade>
|
||
<InputWrapper
|
||
ref={setAnchorEl}
|
||
error={props.error ? 'error' : null}
|
||
className={focused ? 'focused' : ''}
|
||
sx={{
|
||
minHeight: '2.9em',
|
||
maxHeight: '8.6em',
|
||
hoverBorderColor: '#ffffff',
|
||
...props.sx,
|
||
}}
|
||
>
|
||
{value.map((option, index) => (
|
||
<StyledTag
|
||
label={t(option.name)}
|
||
icon={option.icon}
|
||
sx={{ height: '2.1em', ...(props.tagProps ? props.tagProps.sx : {}) }}
|
||
{...getTagProps({ index })}
|
||
/>
|
||
))}
|
||
{value.length > 0 && props.isFilter ? null : <input {...getInputProps()} value={val} />}
|
||
</InputWrapper>
|
||
</div>
|
||
</Tooltip>
|
||
<Grow in={fewerOptions.length > 0}>
|
||
<Listbox sx={props.listBoxProps ? 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) => (
|
||
<li key={option.name} {...getOptionProps({ option, index })}>
|
||
<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={22} height={22} icon={option.icon} />
|
||
</div>
|
||
<Typography variant='inherit' align='left'>
|
||
{t(option.name)}
|
||
</Typography>
|
||
</Button>
|
||
<div style={{ position: 'relative', top: '0.357em' }}>
|
||
<CheckIcon />
|
||
</div>
|
||
</li>
|
||
))}
|
||
{val != null || !props.isFilter ? (
|
||
val.length > 2 ? (
|
||
<Button size='small' fullWidth={true} onClick={() => handleAddNew(getInputProps())}>
|
||
<DashboardCustomizeIcon sx={{ width: '1em', height: '1em' }} />
|
||
{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' }} />
|
||
{props.addNewButtonText}
|
||
</Button>
|
||
</Listbox>
|
||
</Grow>
|
||
</Root>
|
||
);
|
||
}
|