Hook up the select-all checkboxes

This commit is contained in:
Dane Everitt 2022-02-27 13:32:22 -05:00
parent 1096e70052
commit 034b4ad3b0
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
4 changed files with 89 additions and 18 deletions

View file

@ -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'}>

View file

@ -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,9 +56,14 @@ const UsersContainerV2 = () => {
className={'w-56 focus:w-96'}
/>
</div>
<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 indeterminate/>
<Checkbox
checked={selectAllChecked}
indeterminate={selected.length !== users.length}
onChange={onSelectAll}
/>
</div>
<Button.Text square>
<SupportIcon className={'w-4 h-4'}/>
@ -53,6 +75,7 @@ const UsersContainerV2 = () => {
<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>

View file

@ -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>
);
};

View file

@ -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 };