ghost-portal/packages/react-components/src/InputAddressMulti/index.tsx
Jaco Greeff d677d64817
UI support for simple payouts (#2509)
* UI support for simple payouts

* payout modal

* Adjust with era filtering

* Slow as molasses, but seems working

* Adjust th vertical alignment

* Bump API

* Update

* Cleanup reward retrievals

* linting

* Bumps

* Some rendering optimizations

* Re-add counter

* Fix new header linting

* Actual API bump

* Bumps

* Adjustments

* Adjust payouts as stand-alone tab

* Adjust nominations

* rm unused style

* change offsets

* Adjust
2020-04-08 16:39:32 +02:00

199 lines
5.7 KiB
TypeScript

// Copyright 2017-2020 @polkadot/react-components authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import React, { useCallback, useEffect, useState } from 'react';
import styled from 'styled-components';
import { useDebounce } from '@polkadot/react-hooks';
import { useTranslation } from '../translate';
import Input from '../Input';
import Available from './Available';
import Selected from './Selected';
interface Props {
available: string[];
availableLabel: React.ReactNode;
className?: string;
defaultValue?: string[];
help: React.ReactNode;
maxCount: number;
onChange: (values: string[]) => void;
valueLabel: React.ReactNode;
}
// import { DragDropContext, Droppable, DraggableLocation, DroppableProvided, DropResult } from 'react-beautiful-dnd';
// <DragDropContext onDragEnd={_onDragEnd}>
// <Droppable droppableId='available'>
// {(provided: DroppableProvided): React.ReactElement => (
// <div
// className='ui--InputAddressMulti-items'
// // eslint-disable-next-line @typescript-eslint/unbound-method
// ref={provided.innerRef}
// >
// {value.map((address, index): React.ReactNode => (
// <Selected
// address={address}
// index={index}
// key={address}
// onDeselect={_onDeselect}
// />
// ))}
// {provided.placeholder}
// </div>
// )}
// </Droppable>
// </DragDropContext>
// const _onReorder = useCallback(
// (source: DraggableLocation, destination: DraggableLocation): void => {
// const result = Array.from(value);
// const [removed] = result.splice(source.index, 1);
// result.splice(destination.index, 0, removed);
// onChange(uniquesOf(result));
// },
// [onChange, value]
// );
// const _onDeselect = useCallback(
// (index: number): void =>
// onChange(
// uniquesOf([...value.slice(0, index), ...value.slice(index + 1)])
// ),
// [onChange, value]
// );
// const _onDragEnd = useCallback(
// (result: DropResult): void => {
// const { destination, source } = result;
// !!destination && _onReorder(source, destination);
// },
// [_onReorder]
// );
// NOTE Drag code above, disabled since it has massive performance implications
function InputAddressMulti ({ available, availableLabel, className, defaultValue, maxCount, onChange, valueLabel }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [_filter, setFilter] = useState<string>('');
const [selected, setSelected] = useState<string[]>([]);
const filter = useDebounce(_filter);
useEffect((): void => {
defaultValue && setSelected(defaultValue);
}, [defaultValue]);
useEffect((): void => {
selected && onChange(selected);
}, [onChange, selected]);
const _onSelect = useCallback(
(address: string): void =>
setSelected(
(selected: string[]) =>
!selected.includes(address) && (selected.length < maxCount)
? selected.concat(address)
: selected
),
[maxCount]
);
const _onDeselect = useCallback(
(address: string): void =>
setSelected(
(selected: string[]) =>
selected.includes(address)
? selected.filter((a) => a !== address)
: selected
),
[]
);
return (
<div className={`ui--InputAddressMulti ${className}`}>
<Input
autoFocus
className='ui--InputAddressMulti-Input label-small'
onChange={setFilter}
placeholder={t('filter by name, address, or account index')}
value={_filter}
/>
<div className='ui--InputAddressMulti-columns'>
<div className='ui--InputAddressMulti-column'>
<label>{valueLabel}</label>
<div className='ui--InputAddressMulti-items'>
{selected.map((address): React.ReactNode => (
<Selected
address={address}
filter={filter}
key={address}
onDeselect={_onDeselect}
/>
))}
</div>
</div>
<div className='ui--InputAddressMulti-column'>
<label>{availableLabel}</label>
<div className='ui--InputAddressMulti-items'>
{available.map((address): React.ReactNode => (
<Available
address={address}
filter={filter}
isHidden={selected?.includes(address)}
key={address}
onSelect={_onSelect}
/>
))}
</div>
</div>
</div>
</div>
);
}
export default React.memo(styled(InputAddressMulti)`
border-top-width: 0px;
margin-left: 2rem;
width: calc(100% - 2rem);
.ui--InputAddressMulti-Input {
.ui.input {
margin-bottom: 0.25rem;
opacity: 1 !important;
}
}
.ui--InputAddressMulti-columns {
display: inline-flex;
flex-direction: row-reverse;
justify-content: space-between;
width: 100%;
.ui--InputAddressMulti-column {
display: flex;
flex-direction: column;
min-height: 15rem;
max-height: 15rem;
width: 50%;
padding: 0.25rem 0.5rem;
.ui--InputAddressMulti-items {
padding: 0.5rem 0;
background: white;
border: 1px solid rgba(34,36,38,0.15);
border-radius: 0.286rem 0.286rem;
flex: 1;
overflow-y: auto;
.ui--AddressToggle {
padding-left: 0.75rem;
}
}
}
}
`);