@@ -14,7 +14,9 @@ import {
1414 SelectValue ,
1515} from "@/components/ui/select" ;
1616import { EllipsisIcon , SearchIcon } from "lucide-react" ;
17- import { useState } from "react" ;
17+ import { useMemo , useState } from "react" ;
18+
19+ type RoleFilterValue = "ALL ROLES" | TeamAccountRole ;
1820
1921export function ManageMembersSection ( props : {
2022 team : Team ;
@@ -23,6 +25,36 @@ export function ManageMembersSection(props: {
2325} ) {
2426 let topSection : React . ReactNode = null ;
2527
28+ const [ role , setRole ] = useState < RoleFilterValue > ( "ALL ROLES" ) ;
29+ const [ sortBy , setSortBy ] = useState < MemberSortId > ( "date" ) ;
30+
31+ const membersToShow = useMemo ( ( ) => {
32+ let value = props . members ;
33+ if ( role !== "ALL ROLES" ) {
34+ value = value . filter ( ( m ) => m . role === role ) ;
35+ }
36+
37+ switch ( sortBy ) {
38+ case "date" :
39+ value = value . sort (
40+ ( a , b ) => a . createdAt . getTime ( ) - b . createdAt . getTime ( ) ,
41+ ) ;
42+ break ;
43+ case "a-z" :
44+ value = value . sort ( ( a , b ) =>
45+ a . account . name . localeCompare ( b . account . name ) ,
46+ ) ;
47+ break ;
48+ case "z-a" :
49+ value = value . sort ( ( a , b ) =>
50+ b . account . name . localeCompare ( a . account . name ) ,
51+ ) ;
52+ break ;
53+ }
54+
55+ return value ;
56+ } , [ role , props . members , sortBy ] ) ;
57+
2658 if ( ! props . userHasEditPermission ) {
2759 topSection = (
2860 < div className = "border-border border-b p-4" >
@@ -39,22 +71,22 @@ export function ManageMembersSection(props: {
3971 id = "select-all"
4072 className = "border-muted-foreground data-[state=checked]:border-inverted"
4173 disabled = {
42- ! props . userHasEditPermission || props . members . length === 0
74+ ! props . userHasEditPermission || membersToShow . length === 0
4375 }
4476 />
4577 < Label
4678 htmlFor = "select-all"
4779 className = "cursor-pointer text-muted-foreground"
4880 >
49- Select All ({ props . members . length } )
81+ Select All ({ membersToShow . length } )
5082 </ Label >
5183 </ div >
5284
5385 < Button
5486 size = "icon"
5587 variant = "ghost"
5688 className = "!h-auto !w-auto p-1.5"
57- disabled = { ! props . userHasEditPermission || props . members . length === 0 }
89+ disabled = { ! props . userHasEditPermission || membersToShow . length === 0 }
5890 >
5991 < EllipsisIcon className = "size-4 text-muted-foreground" />
6092 </ Button >
@@ -68,7 +100,14 @@ export function ManageMembersSection(props: {
68100
69101 < div className = "h-3" />
70102
71- < FiltersSection disabled = { props . members . length === 0 } />
103+ < FiltersSection
104+ // don't use membersToShow here
105+ disabled = { props . members . length === 0 }
106+ role = { role }
107+ setRole = { setRole }
108+ setSortBy = { setSortBy }
109+ sortBy = { sortBy }
110+ />
72111
73112 < div className = "h-4" />
74113
@@ -77,11 +116,14 @@ export function ManageMembersSection(props: {
77116 { /* Top section */ }
78117 { topSection }
79118
80- { props . members . length > 0 && (
119+ { membersToShow . length > 0 && (
81120 < ul >
82- { props . members . map ( ( member ) => {
121+ { membersToShow . map ( ( member ) => {
83122 return (
84- < li key = { member . accountId } >
123+ < li
124+ key = { member . accountId }
125+ className = "border-border border-b last:border-b-0"
126+ >
85127 < MemberRow
86128 member = { member }
87129 userHasEditPermission = { props . userHasEditPermission }
@@ -93,7 +135,7 @@ export function ManageMembersSection(props: {
93135 ) }
94136
95137 { /* Empty state */ }
96- { props . members . length === 0 && (
138+ { membersToShow . length === 0 && (
97139 < div className = "flex justify-center px-4 py-10" >
98140 < p className = "text-muted-foreground text-sm" > No Members Found</ p >
99141 </ div >
@@ -108,7 +150,7 @@ function MemberRow(props: {
108150 userHasEditPermission : boolean ;
109151} ) {
110152 return (
111- < div className = "flex items-center justify-between border-border border-b px-4 py-4" >
153+ < div className = "flex items-center justify-between px-4 py-4" >
112154 < div className = "flex items-center gap-3 lg:gap-4" >
113155 { /* Checkbox */ }
114156 < Checkbox
@@ -150,7 +192,12 @@ function MemberRow(props: {
150192
151193function FiltersSection ( props : {
152194 disabled : boolean ;
195+ role : RoleFilterValue ;
196+ setRole : ( role : RoleFilterValue ) => void ;
197+ setSortBy : ( sortBy : MemberSortId ) => void ;
198+ sortBy : MemberSortId ;
153199} ) {
200+ const { role, setRole, setSortBy, sortBy } = props ;
154201 return (
155202 < div className = "flex flex-col gap-4 lg:flex-row lg:items-center" >
156203 { /* Search */ }
@@ -164,8 +211,12 @@ function FiltersSection(props: {
164211 </ div >
165212
166213 < div className = "grid grid-cols-2 items-center gap-3 lg:flex" >
167- < RoleSelector disabled = { props . disabled } />
168- < SortMembersBy disabled = { props . disabled } />
214+ < RoleSelector disabled = { props . disabled } role = { role } setRole = { setRole } />
215+ < SortMembersBy
216+ disabled = { props . disabled }
217+ setSortBy = { setSortBy }
218+ sortBy = { sortBy }
219+ />
169220 </ div >
170221 </ div >
171222 ) ;
@@ -175,8 +226,10 @@ type MemberSortId = "date" | "a-z" | "z-a";
175226
176227function SortMembersBy ( props : {
177228 disabled ?: boolean ;
229+ setSortBy : ( sortBy : MemberSortId ) => void ;
230+ sortBy : MemberSortId ;
178231} ) {
179- const [ sortBy , setSortBy ] = useState < MemberSortId > ( "date" ) ;
232+ const { sortBy, setSortBy } = props ;
180233 const valueToLabel : Record < MemberSortId , string > = {
181234 date : "Date" ,
182235 "a-z" : "Name (A-Z)" ,
@@ -211,19 +264,17 @@ function SortMembersBy(props: {
211264
212265function RoleSelector ( props : {
213266 disabled ?: boolean ;
267+ role : RoleFilterValue ;
268+ setRole : ( role : RoleFilterValue ) => void ;
214269} ) {
215- const roles : ( TeamAccountRole | "ALL ROLES" ) [ ] = [
216- "OWNER" ,
217- "MEMBER" ,
218- "ALL ROLES" ,
219- ] ;
220- const [ role , setRole ] = useState < TeamAccountRole | "ALL ROLES" > ( "ALL ROLES" ) ;
270+ const { role, setRole } = props ;
271+ const roles : RoleFilterValue [ ] = [ "OWNER" , "MEMBER" , "ALL ROLES" ] ;
221272
222273 return (
223274 < Select
224275 value = { role }
225276 onValueChange = { ( v ) => {
226- setRole ( v as TeamAccountRole ) ;
277+ setRole ( v as RoleFilterValue ) ;
227278 } }
228279 >
229280 < SelectTrigger
0 commit comments