Hook up the select-all checkboxes
This commit is contained in:
parent
1096e70052
commit
034b4ad3b0
4 changed files with 89 additions and 18 deletions
|
@ -8,9 +8,11 @@ import { Button } from '@/components/elements/button/index';
|
|||
|
||||
interface Props {
|
||||
user: User;
|
||||
selected?: boolean;
|
||||
onRowChange: (user: User, selected: boolean) => void;
|
||||
}
|
||||
|
||||
const UserTableRow = ({ user }: Props) => {
|
||||
const UserTableRow = ({ user, selected, onRowChange }: Props) => {
|
||||
const [ visible, setVisible ] = useState(false);
|
||||
|
||||
return (
|
||||
|
@ -30,7 +32,7 @@ const UserTableRow = ({ user }: Props) => {
|
|||
<tr>
|
||||
<td className={'whitespace-nowrap'}>
|
||||
<div className={'flex justify-end items-center w-8'}>
|
||||
<Checkbox/>
|
||||
<Checkbox checked={selected} onChange={e => onRowChange(user, e.currentTarget.checked)}/>
|
||||
</div>
|
||||
</td>
|
||||
<td className={'pl-6 py-4 whitespace-nowrap'}>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import React, { Fragment, useEffect, useState } from 'react';
|
||||
import http from '@/api/http';
|
||||
import { UUID } from '@/api/definitions';
|
||||
import { Transformers, User } from '@definitions/admin';
|
||||
import { Transition } from '@/components/elements/transitions';
|
||||
import { LockOpenIcon, PlusIcon, SupportIcon, TrashIcon } from '@heroicons/react/solid';
|
||||
import { Button } from '@/components/elements/button/index';
|
||||
import { Checkbox, InputField } from '@/components/elements/inputs';
|
||||
|
@ -8,6 +10,8 @@ import UserTableRow from '@/components/admin/users/UserTableRow';
|
|||
|
||||
const UsersContainerV2 = () => {
|
||||
const [ users, setUsers ] = useState<User[]>([]);
|
||||
const [ selected, setSelected ] = useState<UUID[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = 'Admin | Users';
|
||||
}, []);
|
||||
|
@ -20,6 +24,15 @@ const UsersContainerV2 = () => {
|
|||
.catch(console.error);
|
||||
}, []);
|
||||
|
||||
const onRowChange = (user: User, checked: boolean) => {
|
||||
setSelected((state) => {
|
||||
return checked ? [ ...state, user.uuid ] : selected.filter((uuid) => uuid !== user.uuid);
|
||||
});
|
||||
};
|
||||
|
||||
const selectAllChecked = users.length > 0 && selected.length > 0;
|
||||
const onSelectAll = () => setSelected((state) => state.length > 0 ? [] : users.map(({ uuid }) => uuid));
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={'flex justify-end mb-4'}>
|
||||
|
@ -29,7 +42,11 @@ const UsersContainerV2 = () => {
|
|||
</div>
|
||||
<div className={'relative flex items-center rounded-t bg-neutral-700 px-4 py-2'}>
|
||||
<div className={'mr-6'}>
|
||||
<Checkbox/>
|
||||
<Checkbox
|
||||
checked={selectAllChecked}
|
||||
indeterminate={selected.length !== users.length}
|
||||
onChange={onSelectAll}
|
||||
/>
|
||||
</div>
|
||||
<div className={'flex-1'}>
|
||||
<InputField
|
||||
|
@ -39,20 +56,26 @@ const UsersContainerV2 = () => {
|
|||
className={'w-56 focus:w-96'}
|
||||
/>
|
||||
</div>
|
||||
<div className={'absolute rounded-t bg-neutral-700 w-full h-full top-0 left-0 flex items-center justify-end space-x-4 px-4'}>
|
||||
<div className={'flex-1'}>
|
||||
<Checkbox indeterminate/>
|
||||
<Transition.Fade as={Fragment} show={selected.length > 0} duration={'duration-75'}>
|
||||
<div className={'absolute rounded-t bg-neutral-700 w-full h-full top-0 left-0 flex items-center justify-end space-x-4 px-4'}>
|
||||
<div className={'flex-1'}>
|
||||
<Checkbox
|
||||
checked={selectAllChecked}
|
||||
indeterminate={selected.length !== users.length}
|
||||
onChange={onSelectAll}
|
||||
/>
|
||||
</div>
|
||||
<Button.Text square>
|
||||
<SupportIcon className={'w-4 h-4'}/>
|
||||
</Button.Text>
|
||||
<Button.Text square>
|
||||
<LockOpenIcon className={'w-4 h-4'}/>
|
||||
</Button.Text>
|
||||
<Button.Text square>
|
||||
<TrashIcon className={'w-4 h-4'}/>
|
||||
</Button.Text>
|
||||
</div>
|
||||
<Button.Text square>
|
||||
<SupportIcon className={'w-4 h-4'}/>
|
||||
</Button.Text>
|
||||
<Button.Text square>
|
||||
<LockOpenIcon className={'w-4 h-4'}/>
|
||||
</Button.Text>
|
||||
<Button.Text square>
|
||||
<TrashIcon className={'w-4 h-4'}/>
|
||||
</Button.Text>
|
||||
</div>
|
||||
</Transition.Fade>
|
||||
</div>
|
||||
<table className={'min-w-full rounded bg-neutral-700'}>
|
||||
<thead className={'bg-neutral-900'}>
|
||||
|
@ -64,7 +87,14 @@ const UsersContainerV2 = () => {
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{users.map(user => <UserTableRow user={user} key={user.uuid}/>)}
|
||||
{users.map(user => (
|
||||
<UserTableRow
|
||||
key={user.uuid}
|
||||
user={user}
|
||||
selected={selected.includes(user.uuid)}
|
||||
onRowChange={onRowChange}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import { Transition } from '@headlessui/react';
|
||||
|
||||
type Duration = `duration-${number}`;
|
||||
|
||||
interface Props {
|
||||
as?: React.ElementType;
|
||||
duration?: Duration | [ Duration, Duration ];
|
||||
show: boolean;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export default ({ children, duration, ...props }: Props) => {
|
||||
const [ enterDuration, exitDuration ] = Array.isArray(duration)
|
||||
? duration
|
||||
: (!duration ? [ 'duration-200', 'duration-100' ] : [ duration, duration ]);
|
||||
|
||||
return (
|
||||
<Transition
|
||||
{...props}
|
||||
enter={`ease-out ${enterDuration}`}
|
||||
enterFrom={'opacity-0'}
|
||||
enterTo={'opacity-100'}
|
||||
leave={`ease-in ${exitDuration}`}
|
||||
leaveFrom={'opacity-100'}
|
||||
leaveTo={'opacity-0'}
|
||||
>
|
||||
{children}
|
||||
</Transition>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
import { Transition as TransitionComponent } from '@headlessui/react';
|
||||
import FadeTransition from '@/components/elements/transitions/FadeTransition';
|
||||
|
||||
const Transition = Object.assign(TransitionComponent, {
|
||||
Fade: FadeTransition,
|
||||
});
|
||||
|
||||
export { Transition };
|
Loading…
Reference in a new issue