diff --git a/components/config/Member.tsx b/components/config/Member.tsx index 5eba0653..b747360a 100644 --- a/components/config/Member.tsx +++ b/components/config/Member.tsx @@ -1,17 +1,29 @@ -import { ActionButton } from '@/common/buttons' -import { usePermission } from '@/shell/ConfigurationContext' +import { useState } from 'react' import { ToolsOzoneTeamDefs } from '@atproto/api' import { PlusIcon } from '@heroicons/react/24/outline' -import { MemberEditor } from 'components/team/MemberEditor' -import { MemberList } from 'components/team/MemberList' -import { useMemberList } from 'components/team/useMemberList' -import { useState } from 'react' + +import { ActionButton } from '@/common/buttons' +import { usePermission } from '@/shell/ConfigurationContext' +import { MemberEditor } from '@/team/MemberEditor' +import { MemberList } from '@/team/MemberList' +import RolePicker from '@/team/RolePicker' +import { StatusPicker } from '@/team/StatusPicker' +import { useMemberList } from '@/team/useMemberList' export function MemberConfig() { const [editingMember, setEditingMember] = useState(null) const [showMemberCreateForm, setShowMemberCreateForm] = useState(false) - const { fetchNextPage, data, hasNextPage, isInitialLoading } = useMemberList() + const { + fetchNextPage, + data, + hasNextPage, + isInitialLoading, + disabled, + setDisabled, + roles, + setRoles, + } = useMemberList() const hideEditorForm = () => { if (editingMember) { setEditingMember(null) @@ -23,20 +35,24 @@ export function MemberConfig() { return (
-
+

Manage Members

- {!showMemberCreateForm && !editingMember && canManageTeam && ( - setShowMemberCreateForm((current) => !current)} - > - - Add New - - )} +
+ {!showMemberCreateForm && !editingMember && canManageTeam && ( + setShowMemberCreateForm((current) => !current)} + > + + Add + + )} + + +
{(showMemberCreateForm || !!editingMember) && canManageTeam && ( void + size?: 'sm' | 'md' | 'lg' +} + +const roles = Object.keys(MemberRoleNames) + +const sizeClasses = { + sm: 'px-2 py-0.5 text-xs', + md: 'px-3 py-2 text-sm', + lg: 'px-4 py-3 text-base', +} + +export default function RolePicker({ + values = [], + onChange, + size = 'md', +}: RolePickerProps) { + const [selectedRoles, setSelectedRoles] = useState(values) + + return ( + { + setSelectedRoles(roles) + onChange?.(roles) + }} + multiple + > +
+ {/* Dropdown Button */} + + + {selectedRoles.length > 0 + ? selectedRoles.map(getRoleText).join(', ') + : 'Select Roles'} + + + + {/* Dropdown Menu */} + + + {roles.length === 0 ? ( +
+ No roles available +
+ ) : ( + roles.map((role) => ( + + `relative cursor-pointer select-none py-2 pl-10 pr-4 ${ + active + ? 'bg-gray-100 dark:bg-slate-600 text-gray-900 dark:text-gray-200' + : 'text-gray-900 dark:text-gray-200' + }` + } + > + {({ selected }) => ( + <> + {selected && ( + + + )} + + {getRoleText(role)} + + + )} + + )) + )} +
+
+
+
+ ) +} diff --git a/components/team/StatusPicker.tsx b/components/team/StatusPicker.tsx new file mode 100644 index 00000000..fb903a68 --- /dev/null +++ b/components/team/StatusPicker.tsx @@ -0,0 +1,44 @@ +import { Dropdown } from '@/common/Dropdown' +import { ChevronDownIcon } from '@heroicons/react/24/solid' + +export const StatusPicker = ({ + selected, + onSelect, +}: { + selected?: boolean + onSelect: (disabled?: boolean) => void +}) => { + const selectedText = + selected === undefined ? 'All' : selected ? 'Disabled' : 'Enabled' + return ( + onSelect(), + }, + { + id: 'enabled', + text: 'Enabled', + onClick: () => onSelect(false), + }, + { + id: 'disabled', + text: 'Disabled', + onClick: () => onSelect(true), + }, + ]} + > + + {selectedText} + + + + ) +} diff --git a/components/team/useMemberList.tsx b/components/team/useMemberList.tsx index 95e4a96b..ad1f8a48 100644 --- a/components/team/useMemberList.tsx +++ b/components/team/useMemberList.tsx @@ -1,20 +1,35 @@ import { useLabelerAgent } from '@/shell/ConfigurationContext' import { ToolsOzoneTeamDefs } from '@atproto/api' import { useInfiniteQuery, useQuery } from '@tanstack/react-query' +import { useState } from 'react' +import { MemberRoleNames } from './helpers' export const useMemberList = () => { const labelerAgent = useLabelerAgent() - return useInfiniteQuery({ - queryKey: ['memberList'], + const [roles, setRoles] = useState(Object.keys(MemberRoleNames)) + const [disabled, setDisabled] = useState(false) + + const results = useInfiniteQuery({ + queryKey: ['memberList', { disabled, roles }], queryFn: async ({ pageParam }) => { const { data } = await labelerAgent.tools.ozone.team.listMembers({ - limit: 25, + roles, + disabled, + limit: 50, cursor: pageParam, }) return data }, getNextPageParam: (lastPage) => lastPage.cursor, }) + + return { + ...results, + disabled, + setDisabled, + roles, + setRoles, + } } export const useFullMemberList = () => { diff --git a/tsconfig.json b/tsconfig.json index 8af61e74..46fac595 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -36,6 +36,7 @@ "@/workspace/*": ["components/workspace/*"], "@/sets/*": ["components/sets/*"], "@/setting/*": ["components/setting/*"], + "@/team/*": ["components/team/*"], } }, "include": [