diff --git a/resources/scripts/components/admin/users/UserTableRow.tsx b/resources/scripts/components/admin/users/UserTableRow.tsx index 580ab2bb2..eacb9c55a 100644 --- a/resources/scripts/components/admin/users/UserTableRow.tsx +++ b/resources/scripts/components/admin/users/UserTableRow.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import Checkbox from '@/components/elements/inputs/Checkbox'; import { Dropdown } from '@/components/elements/dropdown'; import { Dialog } from '@/components/elements/dialog'; -import { User } from '@definitions/admin'; +import type { User } from '@definitions/admin'; interface Props { user: User; @@ -12,7 +12,7 @@ interface Props { onRowChange: (user: User, selected: boolean) => void; } -const UserTableRow = ({ user, selected, onRowChange }: Props) => { +function UserTableRow({ user, selected, onRowChange }: Props) { const [visible, setVisible] = useState(false); return ( @@ -56,12 +56,14 @@ const UserTableRow = ({ user, selected, onRowChange }: Props) => { )} - + - + - }>Edit + }> + Edit + }>Reset Password } disabled={!user.isUsingTwoFactor}> Disable 2-FA @@ -76,6 +78,6 @@ const UserTableRow = ({ user, selected, onRowChange }: Props) => { ); -}; +} export default UserTableRow; diff --git a/resources/scripts/components/admin/users/UsersContainer.tsx b/resources/scripts/components/admin/users/UsersContainer.tsx index 87a12d3cc..0cb3398f7 100644 --- a/resources/scripts/components/admin/users/UsersContainer.tsx +++ b/resources/scripts/components/admin/users/UsersContainer.tsx @@ -1,5 +1,6 @@ import { LockOpenIcon, PlusIcon, SupportIcon, TrashIcon } from '@heroicons/react/solid'; import { Fragment, useEffect, useState } from 'react'; +import { NavLink } from 'react-router-dom'; import { useGetUsers } from '@/api/admin/users'; import type { UUID } from '@/api/definitions'; @@ -16,7 +17,7 @@ import { Shape } from '@/components/elements/button/types'; const filters = ['id', 'uuid', 'external_id', 'username', 'email'] as const; -const UsersContainer = () => { +function UsersContainer() { const [search, setSearch] = useDebouncedState('', 500); const [selected, setSelected] = useState([]); const { data: users } = useGetUsers( @@ -42,13 +43,16 @@ const UsersContainer = () => { return (
-
- +
+ + +
-
-
+ +
+
{ onChange={onSelectAll} />
-
+
setSearch(e.currentTarget.value)} />
- 0} duration={'duration-75'}> -
-
+ 0} duration="duration-75"> +
+
{ />
- + - + - +
- - +
+ - - @@ -111,10 +111,10 @@ const UsersContainer = () => { /> ))} - {users && } + {users ? : null}
- + + Email - + +
); -}; +} export default UsersContainer; diff --git a/resources/scripts/components/elements/dropdown/Dropdown.tsx b/resources/scripts/components/elements/dropdown/Dropdown.tsx index be8a20fc3..30c7b4e22 100644 --- a/resources/scripts/components/elements/dropdown/Dropdown.tsx +++ b/resources/scripts/components/elements/dropdown/Dropdown.tsx @@ -1,27 +1,29 @@ -import { ElementType, forwardRef, useMemo } from 'react'; -import * as React from 'react'; import { Menu, Transition } from '@headlessui/react'; -import styles from './style.module.css'; import classNames from 'classnames'; -import DropdownItem from '@/components/elements/dropdown/DropdownItem'; -import DropdownButton from '@/components/elements/dropdown/DropdownButton'; +import type { ElementType, ReactNode } from 'react'; +import { Children as ReactChildren } from 'react'; +import { forwardRef, useMemo } from 'react'; + +import { DropdownButton } from '@/components/elements/dropdown/DropdownButton'; +import { DropdownItem } from '@/components/elements/dropdown/DropdownItem'; +import styles from './style.module.css'; interface Props { as?: ElementType; - children: React.ReactNode; + children: ReactNode; } const DropdownGap = ({ invisible }: { invisible?: boolean }) => (
); -type TypedChild = (React.ReactChild | React.ReactFragment | React.ReactPortal) & { +type TypedChild = ReactNode & { type?: JSX.Element; }; const Dropdown = forwardRef(({ as, children }, ref) => { const [Button, items] = useMemo(() => { - const list = React.Children.toArray(children) as unknown as TypedChild[]; + const list = ReactChildren.toArray(children) as unknown as TypedChild[]; return [ list.filter(child => child.type === DropdownButton), @@ -34,18 +36,18 @@ const Dropdown = forwardRef(({ as, children }, ref) => { } return ( - + {Button} -
{items}
+
{items}
diff --git a/resources/scripts/components/elements/dropdown/DropdownButton.tsx b/resources/scripts/components/elements/dropdown/DropdownButton.tsx index 13e3e38fc..39ce13459 100644 --- a/resources/scripts/components/elements/dropdown/DropdownButton.tsx +++ b/resources/scripts/components/elements/dropdown/DropdownButton.tsx @@ -1,24 +1,29 @@ -import classNames from 'classnames'; -import styles from '@/components/elements/dropdown/style.module.css'; -import { ChevronDownIcon } from '@heroicons/react/solid'; import { Menu } from '@headlessui/react'; -import * as React from 'react'; +import { ChevronDownIcon } from '@heroicons/react/solid'; +import classNames from 'classnames'; +import type { ReactNode } from 'react'; + +import styles from './style.module.css'; interface Props { className?: string; animate?: boolean; - children: React.ReactNode; + children: ReactNode; } -export default ({ className, animate = true, children }: Props) => ( - - {typeof children === 'string' ? ( - <> - {children} - - - ) : ( - children - )} - -); +function DropdownButton({ className, animate = true, children }: Props) { + return ( + + {typeof children === 'string' ? ( + <> + {children} + + ); +} + +export { DropdownButton }; diff --git a/resources/scripts/components/elements/dropdown/DropdownItem.tsx b/resources/scripts/components/elements/dropdown/DropdownItem.tsx index d9f0cf68f..bf8264c0c 100644 --- a/resources/scripts/components/elements/dropdown/DropdownItem.tsx +++ b/resources/scripts/components/elements/dropdown/DropdownItem.tsx @@ -1,43 +1,68 @@ -import { forwardRef } from 'react'; -import * as React from 'react'; import { Menu } from '@headlessui/react'; -import styles from './style.module.css'; import classNames from 'classnames'; +import type { MouseEvent, ReactNode, Ref } from 'react'; +import { forwardRef } from 'react'; +import type { NavLinkProps } from 'react-router-dom'; +import { NavLink } from 'react-router-dom'; + +import styles from './style.module.css'; interface Props { - children: React.ReactNode | ((opts: { active: boolean; disabled: boolean }) => JSX.Element); + children: ReactNode | ((opts: { active: boolean; disabled: boolean }) => JSX.Element); danger?: boolean; disabled?: boolean; className?: string; icon?: JSX.Element; - onClick?: (e: React.MouseEvent) => void; + onClick?: (e: MouseEvent) => void; } -const DropdownItem = forwardRef( - ({ disabled, danger, className, onClick, children, icon: IconComponent }, ref) => { +const DropdownItem = forwardRef>>( + ({ disabled, danger, className, onClick, children, icon: IconComponent, ...props }, ref) => { return ( {({ disabled, active }) => ( - + {'to' in props && props.to !== undefined ? ( + } + className={classNames( + styles.menu_item, + { + [styles.danger]: danger, + [styles.disabled]: disabled, + }, + className, + )} + onClick={onClick} + > + {IconComponent} + {typeof children === 'function' ? children({ disabled, active }) : children} + + ) : ( + )} - onClick={onClick} - > - {IconComponent} - {typeof children === 'function' ? children({ disabled, active }) : children} - + )} ); }, ); -export default DropdownItem; +export { DropdownItem };