react#ReactText TypeScript Examples
The following examples show how to use
react#ReactText.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ColumnsHider.tsx From ke with MIT License | 6 votes |
export function ColumnsHider<T>({ children, onChange, columns, visibleColumns }: ColumnHiderProps<T>): JSX.Element {
const handleChange = useCallback(
(values: ReactText[]) => {
const newVisibleColumns = columns.filter(({ name }) => values.includes(String(name)))
onChange(newVisibleColumns)
},
[onChange, columns]
)
return (
<div>
<Popover placement="right-start">
<PopoverTrigger>
<Button margin="10px 0">Отображаемые колонки</Button>
</PopoverTrigger>
<Portal>
<PopoverContent>
<PopoverArrow />
<PopoverHeader>Выберите отображаемые колонки</PopoverHeader>
<PopoverCloseButton />
<PopoverBody maxHeight="400px" overflow="scroll">
<CheckboxGroup value={visibleColumns.map(({ name }) => name)} onChange={handleChange}>
{columns.map(({ name, header }) => (
<Checkbox value={name} display="block">
{header}
</Checkbox>
))}
</CheckboxGroup>
</PopoverBody>
</PopoverContent>
</Portal>
</Popover>
{children}
</div>
)
}
Example #2
Source File: cellDescToProps.ts From ke with MIT License | 6 votes |
export function cellDescToProps<T, CProps, Extra>(
cellDesc: CellDesc<CProps, T, Extra>,
item: T,
rowIndex: number,
columnIndex: number,
extraGenerator: (item: unknown, rowIndex: number, cellIndex: number) => Extra
): CellProps<CProps> | PropsWithChildren<{}> {
const configOrNode = isCellGenerator(cellDesc)
? cellDesc(item, rowIndex, columnIndex, extraGenerator(item, rowIndex, columnIndex))
: cellDesc
if (typeof configOrNode === 'string' && typeof item === 'object' && configOrNode in item) {
return {
children: (item as Record<string, unknown>)[configOrNode] as ReactText,
}
}
const { value, ...restProps } = isCellConfig(configOrNode) ? configOrNode : { value: configOrNode }
return {
...restProps,
children: isCellNodeGenerator(value)
? value(item, rowIndex, columnIndex, extraGenerator(item, rowIndex, columnIndex))
: value,
}
}
Example #3
Source File: helpers.ts From glide-frontend with GNU General Public License v3.0 | 6 votes |
useCompetitionCakeRewards = (userCakeReward: ReactText) => {
const cakeAsBigNumber = new BigNumber(userCakeReward as string)
const cakeBalance = getBalanceNumber(cakeAsBigNumber)
const cakePriceUsdc = usePriceCakeUsdc()
return {
cakeReward: cakeBalance,
dollarValueOfCakeReward: cakePriceUsdc.gt(0) ? cakeBalance * cakePriceUsdc.toNumber() : null,
}
}
Example #4
Source File: helpers.ts From vvs-ui with GNU General Public License v3.0 | 6 votes |
useCompetitionCakeRewards = (userCakeReward: ReactText) => {
const cakeAsBigNumber = new BigNumber(userCakeReward as string)
const cakeBalance = getBalanceNumber(cakeAsBigNumber)
const croPriceUsdc = usePriceVvsUsdc()
return {
cakeReward: cakeBalance,
dollarValueOfCakeReward: croPriceUsdc.gt(0) ? cakeBalance * croPriceUsdc.toNumber() : null,
}
}
Example #5
Source File: utility.ts From save-food with MIT License | 6 votes |
replaceComma = (value: ReactText): string => `${value}`.replace(/,/g, '.')
Example #6
Source File: DataTable.tsx From jmix-frontend with Apache License 2.0 | 5 votes |
onRowSelectionColumnClicked = (selectedRowKeys: ReactText[]): void => {
if (this.isRowSelectionEnabled) {
this.selectedRowKeys = selectedRowKeys as string[];
}
};
Example #7
Source File: DataTableHelpers.tsx From jmix-frontend with Apache License 2.0 | 5 votes |
/**
*
* @param tableFilters
* @param onFilterChange
* @param entityName
* @param fields
* @param metadata
* @param apiFilters
*/
export function setFilters(
tableFilters: Record<string, Array<ReactText | boolean> | null>,
onFilterChange: FilterChangeCallback,
entityName: string,
fields: string[],
metadata: Metadata,
apiFilters?: JmixEntityFilter[],
) {
let nextApiFilters: JmixEntityFilter[] = [];
if (apiFilters != null && apiFilters.length > 0) {
// We check which of the current API filter conditions needs to be preserved regardless of table filters state.
// Particularly we preserve filters on columns that are not displayed.
const preservedConditions: JmixEntityFilter[] = getPreservedConditions(apiFilters, fields);
if (preservedConditions.length > 0) {
nextApiFilters = [
...nextApiFilters,
...preservedConditions
];
}
}
// Now we modify API filters based on the state of table filters
if (tableFilters) {
fields.forEach((propertyName: string) => {
if (Object.prototype.hasOwnProperty.call(tableFilters, propertyName)
&& tableFilters[propertyName] != null
&& tableFilters[propertyName]!.length > 0) {
const propertyInfoNN = getPropertyInfoNN(propertyName as string, entityName, metadata.entities);
// Enum
if (propertyInfoNN.attributeType === 'ENUM') {
addFilter(nextApiFilters, propertyName, '_in', tableFilters[propertyName]);
return;
}
const {operator, value} = JSON.parse(String(tableFilters[propertyName]![0]));
// Temporal interval
if (operator === '__inInterval') {
const {minDate, maxDate} = value;
addFilter(nextApiFilters, propertyName, '_gte', minDate);
addFilter(nextApiFilters, propertyName, '_lte', maxDate);
return;
}
// Association
if (isRelationProperty(propertyInfoNN)) {
nextApiFilters.push({
[propertyName]: {
id: {
[operator]: value
}
}
});
return;
}
// Everything else
addFilter(nextApiFilters, propertyName, operator, value);
}
});
}
onFilterChange(nextApiFilters);
}
Example #8
Source File: BadgePage.tsx From nuzlocke with BSD 3-Clause "New" or "Revised" License | 5 votes |
function BadgePage(): JSX.Element {
const navigate = useNavigate();
const { badge, game } = useParams();
const { t } = useTranslation('badges');
const selectedGame = useStore(useCallback((state) => state.selectedGame, []));
const [tab, setTab] = useState(0);
const selectedDetail =
!!game && DETAILS[game] && !!badge && typeof Number(badge) === 'number'
? DETAILS[game][Number(badge)]
: null;
useEffect(() => {
if (selectedGame?.value !== game) {
navigate('/');
}
}, [game, navigate, selectedGame]);
useEffect(() => {
if (!selectedDetail) {
navigate('/');
}
}, [game, navigate, selectedDetail]);
const panes = selectedDetail
? selectedDetail.map((gameDetail) => {
return {
menuItem: gameDetail.game,
render: () => (
<Tab.Pane>
<BadgeDetail selectedDetail={selectedDetail[tab]} />
</Tab.Pane>
),
};
})
: null;
const handleTabChange = (newIndex: ReactText) => {
setTab(Number(newIndex));
};
return (
<Page header={t('details')}>
<Tab
activeIndex={tab}
className={styles.tabs}
data-testid="badge-details-tabs"
menu={{ attached: false, tabular: false }}
onTabChange={(e, data) => handleTabChange(data.activeIndex)}
panes={panes}
/>
</Page>
);
}
Example #9
Source File: validation.ts From save-food with MIT License | 5 votes |
checkValidation = (control: InputControl, value: ReactText) =>
!!(!control.error && value && `${value}`.trim() !== '')
Example #10
Source File: AddRule.tsx From nuzlocke with BSD 3-Clause "New" or "Revised" License | 4 votes |
function AddRule(): JSX.Element {
const { t } = useTranslation('rules');
const addRule = useStore(useCallback((state) => state.addRule, []));
const rules = useStore(useCallback((state) => state.rules, []));
const selectedRuleset = useStore(useCallback((state) => state.selectedRuleset, []));
const darkMode = useStore(useCallback((state) => state.darkMode, []));
const [open, setOpen] = useState(false);
const [ruleText, setRuleText] = useState('');
const [level, setLevel] = useState('');
const [types, setTypes] = useState([]);
const [gens, setGens] = useState([]);
const [tab, setTab] = useState(0);
const containsType = rules[selectedRuleset]?.some((rule) => rule.type === 'TYPE');
const containsGen = rules[selectedRuleset]?.some((rule) => rule.type === 'GENERATION');
const containsLevel = rules[selectedRuleset]?.some((rule) => rule.type === 'LEVEL');
const panes = [
{
menuItem: t('text'),
render: () => (
<Tab.Pane>
{t('rule_description')}:
<Input
data-testid="add-rule-input"
maxLength={500}
fluid
onChange={(e, data) => setRuleText(data.value)}
placeholder={t('please_rule')}
value={ruleText}
/>
</Tab.Pane>
),
},
{
menuItem: t('type'),
render: () => (
<Tab.Pane>
{t('allow_only_types')}:
<Dropdown
data-testid="add-rule-type"
disabled={!!containsType}
fluid
multiple
onChange={(e, data) => setTypes([...(data.value as string[])])}
options={Object.keys(TYPE_COUNT).map((key) => {
return { key, text: key, value: key };
})}
placeholder={t('please_type')}
selection
value={types}
/>
{!!containsType && (
<span style={{ color: 'red' }}>{t('already_exists', { rule: t('type') })}</span>
)}
</Tab.Pane>
),
},
{
menuItem: t('generation'),
render: () => (
<Tab.Pane>
{t('allow_only_generations')}:
<Dropdown
data-testid="add-rule-generation"
fluid
disabled={!!containsGen}
multiple
onChange={(e, data) => setGens([...(data.value as number[])])}
options={GENERATIONS.map((gen) => {
return { key: gen, text: gen, value: gen };
})}
placeholder={t('please_generation')}
selection
value={gens}
/>
{!!containsGen && (
<span style={{ color: 'red' }}>{t('already_exists', { rule: t('generation') })}</span>
)}
</Tab.Pane>
),
},
{
menuItem: t('level'),
render: () => (
<Tab.Pane>
{t('max_level_allowed')}:
<Input
data-testid="add-rule-level-input"
disabled={!!containsLevel}
fluid
max={100}
onChange={(e, data) => setLevel(data.value)}
placeholder={t('please_max')}
type="number"
value={level}
/>
{!!containsLevel && (
<span style={{ color: 'red' }}>{t('already_exists', { rule: t('level') })}</span>
)}
</Tab.Pane>
),
},
];
const handleClose = () => {
setOpen(false);
setRuleText('');
};
const handleAdd = () => {
switch (tab) {
case 1:
addRule({ content: types, default: false, type: 'TYPE' });
break;
case 2:
addRule({ content: gens, default: false, type: 'GENERATION' });
break;
case 3:
addRule({ content: level, default: false, type: 'LEVEL' });
break;
case 0:
default:
addRule({ content: ruleText, default: false, type: 'TEXT' });
break;
}
setOpen(false);
setRuleText('');
setLevel('');
setTypes([]);
setGens([]);
};
const handleTabChange = (newIndex: ReactText) => {
setTab(Number(newIndex));
};
const getDisabled = () => {
switch (tab) {
case 1:
return types?.length === 0 || containsType;
case 2:
return gens?.length === 0 || containsGen;
case 3:
return !level || containsLevel;
case 0:
default:
return ruleText?.length === 0;
}
};
return (
<Modal
className={styles.addRule}
open={open}
trigger={
<Button
color="green"
data-testid="add-rule"
disabled={!selectedRuleset}
inverted={darkMode}
onClick={() => setOpen(true)}
type="button"
>
{t('add_rule')}
<Icon name="plus" />
</Button>
}
>
<Modal.Content className={modalStyles.modal}>
<Tab
activeIndex={tab}
className={styles.tabs}
onTabChange={(e, data) => handleTabChange(data.activeIndex)}
panes={panes}
/>
</Modal.Content>
<Modal.Actions>
<Button onClick={handleClose}>{t('cancel', { ns: 'common' })}</Button>
<Button disabled={getDisabled()} onClick={handleAdd} primary>
{t('save', { ns: 'common' })}
</Button>
</Modal.Actions>
</Modal>
);
}
Example #11
Source File: CardUserInfo.tsx From glide-frontend with GNU General Public License v3.0 | 4 votes |
CardUserInfo: React.FC<YourScoreProps> = ({
hasRegistered,
account,
profile,
userLeaderboardInformation,
currentPhase,
}) => {
const { t } = useTranslation()
const [onPresentShareModal] = useModal(
<ShareImageModal profile={profile} userLeaderboardInformation={userLeaderboardInformation} />,
false,
)
const { global, team, volume, next_rank: nextRank } = userLeaderboardInformation
const shouldShowUserRanks = account && hasRegistered
const getMedal = (currentRank: ReactText) => {
if (currentRank === 1) {
return {
current: <MedalGoldIcon />,
next: null,
}
}
if (currentRank <= 10) {
return {
current: <MedalSilverIcon />,
next: <MedalGoldIcon />,
}
}
if (currentRank <= 100) {
return {
current: <MedalBronzeIcon />,
next: <MedalSilverIcon />,
}
}
if (currentRank <= 500) {
return {
current: <MedalPurpleIcon />,
next: <MedalBronzeIcon />,
}
}
if (currentRank > 500) {
return {
current: <MedalTealIcon />,
next: <MedalPurpleIcon />,
}
}
return {
current: <BlockIcon />,
next: <MedalTealIcon />,
}
}
const getNextTier = (currentRank: ReactText) => {
if (currentRank === 1) {
return {
color: null,
rank: null,
}
}
if (currentRank <= 10) {
return {
color: 'GOLD',
rank: 1,
}
}
if (currentRank <= 100) {
return {
color: 'SILVER',
rank: 10,
}
}
if (currentRank <= 500) {
return {
color: 'BRONZE',
rank: 100,
}
}
if (currentRank > 500) {
return {
color: 'PURPLE',
rank: 500,
}
}
return {
color: '',
rank: 500,
}
}
const getHeadingText = () => {
if (!account) {
return t('Check your Rank')
}
if (!hasRegistered) {
return t('You’re not participating this time.')
}
return `@${profile.username}`
}
const getSubHeadingText = () => {
if (!account) {
return t('Connect wallet to view')
}
if (!hasRegistered) {
return t('Sorry, you needed to register during the “entry” period!')
}
return `${profile.team.name}`
}
const headingText = getHeadingText()
const subHeadingText = getSubHeadingText()
const nextTier = userLeaderboardInformation && getNextTier(team)
const medal = userLeaderboardInformation && getMedal(team)
return (
<Flex flexDirection="column" alignItems="center" mt="16px">
<Heading scale="lg" textAlign="center">
{headingText}
</Heading>
<Text textAlign="center" fontSize="14px" color="textSubtle" mt="4px">
{subHeadingText}
</Text>
{shouldShowUserRanks && (
<>
{profile.nft && volume > 0 && (
<Button mt="12px" variant="secondary" scale="sm" onClick={onPresentShareModal}>
{t('Share Score')}
</Button>
)}
<RanksWrapper>
<Flex width="100%" flexDirection={['column', 'row']}>
{volume > 0 && (
<UserRankBox
flex="1"
title={t('Rank in team').toUpperCase()}
footer={userLeaderboardInformation ? t('#%global% Overall', { global: global.toLocaleString() }) : ''}
mr={[0, '8px']}
mb={['8px', 0]}
>
{!userLeaderboardInformation ? (
<Skeleton height="26px" width="110px" />
) : (
<TeamRankTextWrapper>
<Heading textAlign="center" scale="lg" mr="8px">
#{team}
</Heading>
{medal.current}
</TeamRankTextWrapper>
)}
</UserRankBox>
)}
<UserRankBox
flex="1"
title={t('Your volume').toUpperCase()}
footer={t('Since start')}
// Add responsive mr if competition is LIVE
mr={currentPhase.state === LIVE ? [0, null, '8px'] : 0}
>
{!userLeaderboardInformation ? (
<Skeleton height="26px" width="110px" />
) : (
<Heading textAlign="center" scale="lg">
${userLeaderboardInformation && localiseTradingVolume(volume)}
</Heading>
)}
</UserRankBox>
</Flex>
{/* Show next ranks if competition is LIVE */}
{currentPhase.state === LIVE &&
(team === 1 ? (
// If user is first
<NextRankBox
flex="2"
title={t('Your tier: gold').toUpperCase()}
footer={t('Love, The Chefs x')}
currentMedal={medal.current}
hideArrow
>
<Heading scale="lg">{t('HECK YEAH!')}</Heading>
</NextRankBox>
) : (
<NextRankBox
flex="2"
title={`${t('Next tier').toUpperCase()}: ${nextTier.color}`}
footer={t('to become #%rank% in team', { rank: nextTier.rank })}
currentMedal={medal.current}
nextMedal={medal.next}
>
<Heading scale="lg">+${userLeaderboardInformation && localiseTradingVolume(nextRank)}</Heading>
</NextRankBox>
))}
</RanksWrapper>
</>
)}
</Flex>
)
}
Example #12
Source File: ClientConnectionInterruption.tsx From flood with GNU General Public License v3.0 | 4 votes |
ClientConnectionInterruption: FC = observer(() => {
const [error, setError] = useState<string | null>(null);
const [isSubmitting, setSubmitting] = useState<boolean>(false);
const [selection, setSelection] = useState<ReactText>('retry');
const clientConnectionSettingsRef = useRef<ClientConnectionSettings | null>(null);
return (
<Panel spacing="large">
<Form
onSubmit={async () => {
setSubmitting(true);
if (selection === 'config') {
const currentUsername = AuthStore.currentUser.username;
const connectionSettings = clientConnectionSettingsRef.current;
if (currentUsername == null || connectionSettings == null) {
setError('connection.settings.error.empty');
setSubmitting(false);
return;
}
try {
await AuthActions.updateUser(currentUsername, {
client: connectionSettings,
})
.then(() => {
// do nothing.
})
.catch((e) => {
setError('general.error.unknown');
throw e;
});
} catch {
setSubmitting(false);
return;
}
}
await ClientActions.testConnection()
.then(() => {
FloodActions.restartActivityStream();
})
.catch(() => {
setError('connection-interruption.verification-error');
});
setSubmitting(false);
}}
>
<PanelHeader>
<h1>
<Trans id="connection-interruption.heading" />
</h1>
</PanelHeader>
<PanelContent>
{error && (
<FormRow>
<FormError>
<Trans id={error} />
</FormError>
</FormRow>
)}
{AuthStore.currentUser.isAdmin ? (
<FormRow>
<Select id="action" onSelect={setSelection} defaultID="retry">
<SelectItem key="retry" id="retry">
<Trans id="connection-interruption.action.selection.retry" />
</SelectItem>
<SelectItem key="config" id="config">
<Trans id="connection-interruption.action.selection.config" />
</SelectItem>
</Select>
</FormRow>
) : (
<p className="copy--lead">
<Trans id="connection-interruption.not.admin" />
</p>
)}
{selection === 'config' && (
<ClientConnectionSettingsForm
onSettingsChange={(settings) => {
clientConnectionSettingsRef.current = settings;
}}
/>
)}
</PanelContent>
<PanelFooter hasBorder>
<FormRow justify="end">
{selection === 'retry' && (
<Button type="submit" isLoading={isSubmitting}>
<Trans id="button.retry" />
</Button>
)}
{selection === 'config' && (
<Button type="submit" isLoading={isSubmitting}>
<Trans id="button.save" />
</Button>
)}
</FormRow>
</PanelFooter>
</Form>
</Panel>
);
})
Example #13
Source File: DirectoryFileList.tsx From flood with GNU General Public License v3.0 | 4 votes |
DirectoryFiles: FC<DirectoryFilesProps> = ({depth, items, hash, path, onItemSelect}: DirectoryFilesProps) => {
const [copiedToClipboard, setCopiedToClipboard] = useState<number | null>(null);
const contentPermalinks = useRef<Record<number, string | null>>({});
if (items == null) {
return null;
}
const files = Object.values(items)
.sort((a, b) => a.filename.localeCompare(b.filename))
.map((file) => {
const isSelected = (items && items[file.filename] && items[file.filename].isSelected) || false;
const classes = classnames(
'directory-tree__node file',
'directory-tree__node--file directory-tree__node--selectable',
{
'directory-tree__node--selected': isSelected,
},
);
return (
<div className={classes} key={file.filename} title={file.filename}>
<div className="file__label file__detail">
<div className="file__checkbox directory-tree__checkbox">
<div className="directory-tree__checkbox__item directory-tree__checkbox__item--checkbox">
<Checkbox
checked={isSelected}
id={`${file.index}`}
onClick={() =>
onItemSelect({
type: 'file',
depth,
path: [...path, file.filename],
select: !isSelected,
})
}
/>
</div>
<div className="directory-tree__checkbox__item directory-tree__checkbox__item--icon">
<FileIcon />
</div>
</div>
<div className="file__name">
{/* TODO: Add a WebAssembly decoding player if the feature is popular */}
<a
href={`${ConfigStore.baseURI}api/torrents/${hash}/contents/${file.index}/data`}
style={{textDecoration: 'none'}}
target="_blank"
rel="noreferrer"
>
{file.filename}
</a>
</div>
</div>
<div className="file__detail file__detail--secondary">
<Size value={file.sizeBytes} precision={1} />
</div>
<div className="file__detail file__detail--secondary">{Math.trunc(file.percentComplete)}%</div>
<div
className="file__detail file__detail--secondary
file__detail--priority"
>
<PriorityMeter
key={`${file.index}-${file.filename}`}
level={file.priority}
id={file.index}
maxLevel={2}
onChange={(fileIndex: ReactText, priorityLevel: number) =>
TorrentActions.setFilePriority(hash, {
indices: [Number(fileIndex)],
priority: priorityLevel,
})
}
priorityType="file"
/>
</div>
{typeof navigator.clipboard?.writeText === 'function' && (
<button
className="file__detail file__detail--secondary file__detail--clipboard"
type="button"
onClick={() => {
const copy = (link: string): void => {
if (link !== '') {
if (typeof navigator.share === 'function') {
navigator
.share({
title: file.filename,
url: link,
})
.then(() => setCopiedToClipboard(file.index));
} else {
navigator.clipboard.writeText(link).then(() => setCopiedToClipboard(file.index));
}
}
};
// Safari does not support async operations inside "user gesture" handler.
// Otherwise the write to clipboard will be rejected for "security reasons".
// As such, we cache the token, so next click can be synchronous. Incompatible
// morons make everyone's life hard.
const link = contentPermalinks.current[file.index];
if (link != null) {
copy(link);
} else {
contentPermalinks.current[file.index] = '';
TorrentActions.getTorrentContentsDataPermalink(hash, [file.index]).then(
(url) => {
contentPermalinks.current[file.index] = url;
copy(url);
},
() => {
contentPermalinks.current[file.index] = null;
},
);
}
}}
>
{copiedToClipboard === file.index ? <Checkmark /> : <Clipboard />}
</button>
)}
</div>
);
});
return <div className="directory-tree__node directory-tree__node--file-list">{files}</div>;
}
Example #14
Source File: useSelection.tsx From amiya with MIT License | 4 votes |
export default function useSelection(_props: UseSelectionProps): UseSelectionReturns {
const { rowKey, selectionType, onSelectionChange, selectShowKey, rowSelection } = _props
const [selectionKeys, setSelectionKeys] = useState<Array<ReactText>>([])
const [selection, setSelection] = useState<Array<Row>>([])
let tableRowSelection: AnyKeyProps | undefined
if (selectionType) {
tableRowSelection = {
...rowSelection,
type: selectionType,
selectedRowKeys: selectionKeys,
onSelect: (record: Row, selected: boolean) => {
if (selectionType === 'radio') {
changeRadioSelection(record)
} else {
selected ? addSelection(record) : removeSelection(null, record)
}
},
onSelectAll: (selected: boolean, selectedRows: Array<Row>, changeRows: Array<Row>) => {
selected ? addSelectionArray(selectedRows) : removeSelectionArray(changeRows)
}
}
}
/**
* 清空所有选项
*/
const clearSelection = () => {
setSelectionKeys([])
setSelection([])
}
/**
* 设置选中的行
*/
const setDefaultSelection = (selection: AnyKeyProps[]) => {
setSelection(selection)
setSelectionKeys(selection.map(row => getKey(row, rowKey)))
}
/**
* 添加选项
*/
const addDefaultSelection = (addSelection: AnyKeyProps[]) => {
// @ts-ignore
let newSelection = [...selection]
addSelection.forEach(row => {
if (!selectionKeys.includes(getKey(row, rowKey))) {
newSelection.push(row)
}
})
setSelection(newSelection)
setSelectionKeys(newSelection.map(row => getKey(row, rowKey)))
}
const changeRadioSelection = (row: AnyKeyProps) => {
let newKeys = []
let newSelection = []
newKeys.push(getKey(row, rowKey))
newSelection.push(row)
setSelectionKeys(newKeys)
setSelection(newSelection)
}
/**
* 添加选项(单个)
* @param row 某一条选项
*/
const addSelection = (row: AnyKeyProps) => {
// @ts-ignore
let newKeys = [...selectionKeys]
let newSelection = [...selection]
newKeys.push(getKey(row, rowKey))
newSelection.push(row)
setSelectionKeys(newKeys)
setSelection(newSelection)
}
/**
* 添加选项(数组)
* @param rows 项目列表
*/
const addSelectionArray = (rows: Array<AnyKeyProps>) => {
let newKeys = [...selectionKeys]
let newSelection = [...selection]
rows.forEach(row => {
if (!row) {
return
}
let key = getKey(row, rowKey)
if (!newKeys.includes(key)) {
newKeys.push(key)
newSelection.push(row)
}
})
setSelectionKeys(newKeys)
setSelection(newSelection)
}
/**
* 移除某个选项
* @param i 移除选项的 index
*/
const removeSelection = (i: number | null, record?: AnyKeyProps) => {
let newKeys = [...selectionKeys]
let newSelection = [...selection]
if (i === null && record) {
i = newKeys.findIndex(key => key === getKey(record, rowKey))
}
if (typeof i === 'number') {
newKeys.splice(i, 1)
newSelection.splice(i, 1)
}
setSelectionKeys(newKeys)
setSelection(newSelection)
}
/**
* 移除一组选项
* @param rows 移除选项
*/
const removeSelectionArray = (rows: Array<Row>) => {
let newKeys = [...selectionKeys]
let newSelection = [...selection]
rows.forEach(row => {
let index = newKeys.findIndex(item => item === getKey(row, rowKey))
if (index >= 0) {
newKeys.splice(index, 1)
newSelection.splice(index, 1)
}
})
setSelectionKeys(newKeys)
setSelection(newSelection)
}
/** Popover 弹窗的提示 */
const popContent = (
<div className="ay-search-poper">
{selection.map((row, i) => {
return (
<Tag key={getKey(row, rowKey)} closable className="mb" onClose={() => removeSelection(i)}>
{row[selectShowKey || 'name']}
</Tag>
)
})}
</div>
)
const message = (
<div>
<span>
{locale.table.selectedBefore}
<Popover title={locale.table.selectedTitle} content={popContent}>
<a>{selection.length}</a>
</Popover>
{locale.table.selectedAfter}
</span>
<AyAction className="ml" type="link" size="small" onClick={clearSelection}>
{locale.table.selectedClear}
</AyAction>
</div>
)
/** 头部已选中的提示 */
const header = selectionKeys.length ? <Alert className="ay-search-table-alert" message={message} showIcon /> : ''
useEffect(() => {
if (onSelectionChange) {
onSelectionChange(selection, selectionKeys)
}
}, [onSelectionChange, selection])
return {
header,
message,
tableRowSelection,
selection,
clearSelection,
removeSelection,
setSelection: setDefaultSelection,
addSelection: addDefaultSelection
}
}
Example #15
Source File: CardUserInfo.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
CardUserInfo: React.FC<YourScoreProps> = ({
hasRegistered,
account,
profile,
userLeaderboardInformation,
currentPhase,
}) => {
const { t } = useTranslation()
const [onPresentShareModal] = useModal(
<ShareImageModal profile={profile} userLeaderboardInformation={userLeaderboardInformation} />,
false,
)
const { global, team, volume, next_rank: nextRank } = userLeaderboardInformation
const shouldShowUserRanks = account && hasRegistered
const getMedal = (currentRank: ReactText) => {
if (currentRank === 1) {
return {
current: <MedalGoldIcon />,
next: null,
}
}
if (currentRank <= 10) {
return {
current: <MedalSilverIcon />,
next: <MedalGoldIcon />,
}
}
if (currentRank <= 100) {
return {
current: <MedalBronzeIcon />,
next: <MedalSilverIcon />,
}
}
if (currentRank <= 500) {
return {
current: <MedalPurpleIcon />,
next: <MedalBronzeIcon />,
}
}
if (currentRank > 500) {
return {
current: <MedalTealIcon />,
next: <MedalPurpleIcon />,
}
}
return {
current: <BlockIcon />,
next: <MedalTealIcon />,
}
}
const getNextTier = (currentRank: ReactText) => {
if (currentRank === 1) {
return {
color: null,
rank: null,
}
}
if (currentRank <= 10) {
return {
color: 'GOLD',
rank: 1,
}
}
if (currentRank <= 100) {
return {
color: 'SILVER',
rank: 10,
}
}
if (currentRank <= 500) {
return {
color: 'BRONZE',
rank: 100,
}
}
if (currentRank > 500) {
return {
color: 'PURPLE',
rank: 500,
}
}
return {
color: '',
rank: 500,
}
}
const getHeadingText = () => {
if (!account) {
return t('Check your Rank')
}
if (!hasRegistered) {
return t('You’re not participating this time.')
}
return `@${profile.username}`
}
const getSubHeadingText = () => {
if (!account) {
return t('Connect wallet to view')
}
if (!hasRegistered) {
return t('Sorry, you needed to register during the “entry” period!')
}
return `${profile.team.name}`
}
const headingText = getHeadingText()
const subHeadingText = getSubHeadingText()
const nextTier = userLeaderboardInformation && getNextTier(team)
const medal = userLeaderboardInformation && getMedal(team)
return (
<Flex flexDirection="column" alignItems="center" mt="16px">
<Heading scale="lg" textAlign="center">
{headingText}
</Heading>
<Text textAlign="center" fontSize="14px" color="textSubtle" mt="4px">
{subHeadingText}
</Text>
{shouldShowUserRanks && (
<>
{profile.nft && volume > 0 && (
<Button mt="12px" variant="secondary" scale="sm" onClick={onPresentShareModal}>
{t('Share Score')}
</Button>
)}
<RanksWrapper>
<Flex width="100%" flexDirection={['column', 'row']}>
{volume > 0 && (
<UserRankBox
flex="1"
title={t('Rank in team').toUpperCase()}
footer={userLeaderboardInformation ? t('#%global% Overall', { global: global.toLocaleString() }) : ''}
mr={[0, '8px']}
mb={['8px', 0]}
>
{!userLeaderboardInformation ? (
<Skeleton height="26px" width="110px" />
) : (
<TeamRankTextWrapper>
<Heading textAlign="center" scale="lg" mr="8px">
#{team}
</Heading>
{medal.current}
</TeamRankTextWrapper>
)}
</UserRankBox>
)}
<UserRankBox
flex="1"
title={t('Your volume').toUpperCase()}
footer={t('Since start')}
// Add responsive mr if competition is LIVE
mr={currentPhase.state === LIVE ? [0, null, '8px'] : 0}
>
{!userLeaderboardInformation ? (
<Skeleton height="26px" width="110px" />
) : (
<Heading textAlign="center" scale="lg">
${userLeaderboardInformation && localiseTradingVolume(volume)}
</Heading>
)}
</UserRankBox>
</Flex>
{/* Show next ranks if competition is LIVE */}
{currentPhase.state === LIVE &&
(team === 1 ? (
// If user is first
<NextRankBox
flex="2"
title={t('Your tier: gold').toUpperCase()}
footer={t('Love, The Chefs x')}
currentMedal={medal.current}
hideArrow
>
<Heading scale="lg">{t('HECK YEAH!')}</Heading>
</NextRankBox>
) : (
<NextRankBox
flex="2"
title={`${t('Next tier').toUpperCase()}: ${nextTier.color}`}
footer={t('to become #%rank% in team', { rank: nextTier.rank })}
currentMedal={medal.current}
nextMedal={medal.next}
>
<Heading scale="lg">+${userLeaderboardInformation && localiseTradingVolume(nextRank)}</Heading>
</NextRankBox>
))}
</RanksWrapper>
</>
)}
</Flex>
)
}
Example #16
Source File: Payment.tsx From save-food with MIT License | 4 votes |
Payment = ({ navigation }: Props) => {
const { useSubscribe, setSettings } = useSettingsContext()
const settings = useSubscribe((s) => s.settings)
const translations = useSubscribe((s) => ({
...s.translations.Payment,
...s.translations.common,
}))
const [loading, setLoading] = useState(false)
const [showModal, setShowModal] = useState(false)
const [amount, setAmount] = useState<number>()
const [email, setEmail] = useState<ReactText>(settings.email)
const [controls, setControls] = useState<InputsControl>({
email: {
label: translations.emailLabel,
characterRestriction: 70,
keyboardType: 'email-address',
email: true,
},
})
const payForFoodHandler = async () => {
setLoading(true)
if (email && !controls.email.error) {
await fetch(`${config.SAVE_FOOD_API}/send-email`, {
method: 'POST',
body: JSON.stringify({ email, lang: settings.lang }),
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
})
.then(async (res) => {
if (res.status !== 200) {
throw new Error(`Response status: ${res.status}`)
}
await logEvent('sendEmail', {
component: 'Payment',
})
})
.catch((err) => {
// eslint-disable-next-line no-console
console.warn(err)
sentryError(err)
})
setSettings(await changeEmail(`${email}`))
}
const ids = navigation.getParam('ids', undefined)
if (!ids) {
// eslint-disable-next-line no-console
console.warn('Missing food ids for payment')
sentryError('Missing food ids for payment')
}
navigation.navigate('List', { ids })
}
const itemOnPressHandler = async (item: Organization) => {
await logEvent('itemOnPress', {
component: 'Payment',
item,
})
await WebBrowser.openBrowserAsync(item.url)
}
const renderItem = ({ item }: { item: Organization }) => (
<TouchableOpacity
activeOpacity={1}
style={[styles.imageContainer, shadow]}
onPress={() => itemOnPressHandler(item)}
>
<Image style={styles.image} source={item.image} />
</TouchableOpacity>
)
useEffect(() => {
const amount = navigation.getParam('amount', 0)
setAmount(amount)
}, [])
useAsyncEffect(async () => {
const paidFoods = await getPaidWastedFoods()
if (paidFoods.length === 0) {
setShowModal(true)
}
}, [])
return (
<View style={styles.flex}>
<StatusBar barStyle='dark-content' translucent backgroundColor='transparent' />
<Header
leftComponent={
<Icon color={blackColor} onPress={() => navigation.goBack()} variant='backIcon' />
}
centerComponent={
<Text numberOfLines={1} style={styles.header}>
{translations.amount} {amount} {settings.currency}
</Text>
}
rightComponent={
<Icon
color={blackColor}
style={styles.infoIcon}
onPress={() => setShowModal(true)}
type='material'
name='info-outline'
/>
}
/>
<Modal
visible={showModal}
toggleModal={() => setShowModal(!showModal)}
title={translations.paymentInfoTitle}
buttons={[{ text: 'Ok', onPress: () => setShowModal(false) }]}
>
<View>
<Text style={styles.infoText}>{translations.paymentInfo1}</Text>
<Text style={styles.infoText}>{translations.paymentInfo2}</Text>
<Text style={styles.infoText}>{translations.paymentInfo3}</Text>
</View>
</Modal>
<ScrollView scrollEventThrottle={200} directionalLockEnabled>
<View style={styles.inputWrapper}>
<Input
inputConfig={controls.email}
translations={translations}
focus={false}
value={email}
changed={(value, control) => {
setEmail(value)
setControls({ email: control })
}}
/>
</View>
<View style={styles.contentWrapper}>
<Text style={styles.contentTextWrapper}>
<Text style={styles.lightText}>{translations.paymentHeaderText1} </Text>
<Text style={styles.boldText}>{translations.paymentHeaderText2} </Text>
<Text style={styles.lightText}>{translations.paymentHeaderText3} </Text>
<Text style={styles.boldText}>{translations.paymentHeaderText4} </Text>
<Text style={styles.lightText}>:</Text>
</Text>
<Carousel
layout='default'
removeClippedSubviews={false}
data={charityOrganizations}
sliderWidth={200}
itemWidth={200}
renderItem={renderItem}
activeSlideAlignment='center'
containerCustomStyle={styles.slider}
loop
/>
<Text style={styles.contentTextWrapper}>
<Text style={styles.lightText}>{translations.paymentFooterText1} </Text>
<Text style={styles.boldText}>{translations.paymentFooterText2} </Text>
<Text style={styles.lightText}>{translations.paymentFooterText3}</Text>
</Text>
</View>
</ScrollView>
<View style={[styles.paymentButtonContainer, shadow]}>
<View style={styles.paymentButtonWrapper}>
<Button
loading={loading}
buttonStyle={styles.paymentButton}
titleStyle={styles.paymentButtonTitle}
onPress={payForFoodHandler}
title={translations.donationSent}
/>
</View>
</View>
</View>
)
}