123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- /**
- * Transfer
- * @author: oldj
- * @homepage: https://oldj.net
- */
- import { useModel } from '@@/plugin-model/useModel'
- import { ArrowBackIcon, ArrowForwardIcon } from '@chakra-ui/icons'
- import { Box, Center, Grid, IconButton, VStack } from '@chakra-ui/react'
- import React, { useState } from 'react'
- import clsx from 'clsx'
- import styles from './Transfer.less'
- type IdType = string
- interface ITransferSourceObject {
- id: IdType
- [key: string]: any
- }
- interface IListProps {
- data: ITransferSourceObject[]
- selected_keys: IdType[]
- setSelectedKeys: (ids: IdType[]) => void
- }
- interface Props {
- dataSource: ITransferSourceObject[]
- targetKeys: IdType[]
- render?: (obj: ITransferSourceObject) => React.ReactElement
- onChange?: (next_target_keys: IdType[]) => void
- }
- const Transfer = (props: Props) => {
- const { dataSource, targetKeys, render, onChange } = props
- const { lang } = useModel('useI18n')
- const [right_keys, setRightKeys] = useState<IdType[]>(targetKeys)
- const [left_selectd_keys, setLeftSelectedKeys] = useState<IdType[]>([])
- const [right_selectd_keys, setRightSelectedKeys] = useState<IdType[]>([])
- const List = (list_props: IListProps) => {
- const { data, selected_keys, setSelectedKeys } = list_props
- const toggleSelect = (id: IdType) => {
- setSelectedKeys(
- selected_keys.includes(id)
- ? selected_keys.filter((i) => i != id)
- : [...selected_keys, id],
- )
- }
- return (
- <div className={styles.list}>
- {data.map((item) => {
- if (!item || !item.id) return null
- const is_selected = selected_keys.includes(item.id)
- return (
- <Box
- key={item.id}
- className={clsx(styles.item, is_selected && styles.selected)}
- px={3}
- py={1}
- onClick={() => toggleSelect(item.id)}
- >
- {render ? render(item) : item.title || item.id}
- </Box>
- )
- })}
- </div>
- )
- }
- const moveLeftToRight = () => {
- let result = [...right_keys, ...left_selectd_keys]
- setRightKeys(result)
- setLeftSelectedKeys([])
- onChange && onChange(result)
- }
- const moveRightToLeft = () => {
- let result = right_keys.filter((i) => !right_selectd_keys.includes(i))
- setRightKeys(result)
- setRightSelectedKeys([])
- onChange && onChange(result)
- }
- return (
- <div className={styles.root}>
- <Grid templateColumns="minmax(0, 1fr) 40px minmax(0, 1fr)" gap={1}>
- <Box borderWidth="1px" borderRadius="md">
- <Box className={styles.title} borderBottomWidth={1} px={3} py={1}>
- {lang.all}{' '}
- <span>
- (
- {left_selectd_keys.length === 0
- ? dataSource.length
- : `${left_selectd_keys.length}/${dataSource.length}`}
- )
- </span>
- </Box>
- <List
- data={dataSource.filter((i) => !right_keys.includes(i.id))}
- selected_keys={left_selectd_keys}
- setSelectedKeys={setLeftSelectedKeys}
- />
- </Box>
- <Center h="100%">
- <VStack>
- <IconButton
- size="sm"
- variant="outline"
- aria-label="Move to right"
- icon={<ArrowForwardIcon />}
- isDisabled={left_selectd_keys.length === 0}
- onClick={moveLeftToRight}
- />
- <IconButton
- size="sm"
- variant="outline"
- aria-label="Move to left"
- icon={<ArrowBackIcon />}
- isDisabled={right_selectd_keys.length === 0}
- onClick={moveRightToLeft}
- />
- </VStack>
- </Center>
- <Box borderWidth="1px" borderRadius="md">
- <Box className={styles.title} borderBottomWidth={1} px={3} py={1}>
- {lang.selected}{' '}
- <span>
- (
- {right_selectd_keys.length === 0
- ? right_keys.length
- : `${right_selectd_keys.length}/${right_keys.length}`}
- )
- </span>
- </Box>
- <List
- data={
- right_keys.map((id) =>
- dataSource.find((i) => i.id === id),
- ) as ITransferSourceObject[]
- }
- selected_keys={right_selectd_keys}
- setSelectedKeys={setRightSelectedKeys}
- />
- </Box>
- </Grid>
- </div>
- )
- }
- export default Transfer
|