@@ -9,12 +9,12 @@ import AdminTableCell from '@/components/admin/AdminTableCell';
99import AdminTableTopContent from '@/components/admin/AdminTableTopContent' ;
1010import AdminTableBottomContent from '@/components/admin/AdminTableBottomContent' ;
1111
12- import { users } from '@/mock/users ' ;
12+ import { useAuthenticatedApi } from '@/hooks/useAuthenticatedApi ' ;
1313
1414const columns = [
1515 { name : 'NAME' , uid : 'name' } ,
1616 { name : 'MAJOR / ID' , uid : 'major' } ,
17- { name : 'PAYMENT' , uid : 'status ' } ,
17+ { name : 'PAYMENT' , uid : 'isPayed ' } ,
1818] ;
1919
2020const statusColorMap = {
@@ -24,31 +24,63 @@ const statusColorMap = {
2424
2525export default function Page ( ) {
2626 const router = useRouter ( ) ;
27+ const { apiClient } = useAuthenticatedApi ( ) ;
2728
28- // 추후 users 를 사용해 데이터를 받아오고, totalUsers를 사용해 페이지네이션 만들 예정
29- const [ page , setPage ] = React . useState ( 1 ) ; // 현재 페이지 상태 (추후 페이지 상태에 따라 api 통신으로 데이터 불러오기)
29+ const [ page , setPage ] = React . useState ( 1 ) ;
3030
3131 const [ modalOpen , setModalOpen ] = React . useState ( false ) ; // 모달 열림 상태
3232 const modalClosing = useRef ( false ) ; // 모달이 닫히는 상태를 추적
3333
3434 const [ selectedUser , setSelectedUser ] = React . useState ( null ) ; // 선택된 사용자 데이터
3535 const [ searchValue , setSearchValue ] = React . useState ( '' ) ; // 검색 입력 상태
36+ const [ query , setQuery ] = React . useState ( '' ) ; // API 호출시 검색 내용
37+ const [ loading , setLoading ] = React . useState ( false ) ;
38+ const [ error , setError ] = React . useState ( '' ) ;
39+ const [ currentUsers , setCurrentUsers ] = React . useState ( [ ] ) ;
40+ const [ totalUsers , setTotalUsers ] = React . useState ( 0 ) ;
41+ const [ totalPages , setTotalPages ] = React . useState ( 0 ) ;
3642
3743 const rowsPerPage = 10 ; //한 페이지당 표시될 유저 수
38- const totalUsers = 110 ; //총 유저 수 (총 페이지 표시를 위함)
3944
40- // 현재 페이지 데이터 계산 (임시)
41- const currentUsers = React . useMemo ( ( ) => {
42- const startIndex = ( page - 1 ) * rowsPerPage ;
43- const endIndex = startIndex + rowsPerPage ;
44- return users . slice ( startIndex , endIndex ) ;
45- } , [ page , rowsPerPage ] ) ;
46-
47- const totalPages = React . useMemo ( ( ) => Math . ceil ( totalUsers / rowsPerPage ) , [ totalUsers , rowsPerPage ] ) ;
48-
49- const renderCell = useCallback ( ( user , columnKey ) =>
50- < AdminTableCell user = { user } columnKey = { columnKey } />
51- , [ ] ) ;
45+ const fetchUsers = useCallback ( async ( ) => {
46+ setLoading ( true ) ;
47+ setError ( '' ) ;
48+ try {
49+ const params = {
50+ page : page - 1 ,
51+ size : rowsPerPage ,
52+ sort : 'createdAt' ,
53+ dir : 'DESC' ,
54+ question : query || undefined ,
55+ } ;
56+ const res = await apiClient . get ( '/recruit/members' , { params } ) ;
57+ const list = Array . isArray ( res ?. data ?. data ) ? res . data . data : [ ] ;
58+ const total = res ?. data ?. meta ?. totalElements ?? list . length ;
59+ const computedTotalPages = Math . max ( 1 , Math . ceil ( total / rowsPerPage ) ) ;
60+
61+ setCurrentUsers ( list ) ;
62+ setTotalUsers ( total ) ;
63+ setTotalPages ( computedTotalPages ) ;
64+ } catch ( err ) {
65+ setError ( String ( err ?. message || 'failed to load users' ) ) ;
66+ setCurrentUsers ( [ ] ) ;
67+ setTotalUsers ( 0 ) ;
68+ } finally {
69+ setLoading ( false ) ;
70+ }
71+ } , [ apiClient , page , rowsPerPage , query ] ) ;
72+
73+ const renderCell = useCallback ( ( user , columnKey ) => {
74+ const normalizedUser = {
75+ ...user ,
76+ name : user ?. name ?? '' ,
77+ major : user ?. major ?? '' ,
78+ studentId : user ?. studentId ?? '' ,
79+ isPayed : typeof user ?. isPayed === 'boolean' ? user . isPayed : '' ,
80+ phoneNumber : user ?. phoneNumber ?? '' ,
81+ } ;
82+ return < AdminTableCell user = { normalizedUser } columnKey = { columnKey } /> ;
83+ } , [ ] ) ;
5284
5385 const handleRowClick = ( user ) => {
5486 if ( modalClosing . current ) return ; // 모달이 닫히는 중에는 클릭 무시
@@ -57,8 +89,8 @@ export default function Page() {
5789 } ;
5890
5991 const handleSearch = ( ) => {
60- //추후 api 연결 함수로 변경 예정
61- console . log ( searchValue ) ; //임시
92+ setPage ( 1 ) ;
93+ setQuery ( ( searchValue || '' ) . trim ( ) ) ;
6294 } ;
6395
6496 const handleCloseModal = ( ) => {
@@ -69,6 +101,17 @@ export default function Page() {
69101 } , 300 ) ;
70102 } ;
71103
104+ useEffect ( ( ) => {
105+ if ( searchValue === '' && query !== '' ) {
106+ setPage ( 1 ) ;
107+ setQuery ( '' ) ;
108+ }
109+ } , [ searchValue , query ] ) ;
110+
111+ useEffect ( ( ) => {
112+ fetchUsers ( ) ;
113+ } , [ fetchUsers ] ) ;
114+
72115 return (
73116 < >
74117 < div >
@@ -89,11 +132,15 @@ export default function Page() {
89132 </ TableColumn >
90133 ) }
91134 </ TableHeader >
92- < TableBody items = { currentUsers } >
135+ < TableBody
136+ items = { currentUsers }
137+ isLoading = { loading }
138+ emptyContent = { loading ? '불러오는 중...' : '데이터가 없습니다.' }
139+ >
93140 { ( item ) => (
94141 < TableRow
95142 className = 'hover:bg-[#35353b99] cursor-pointer'
96- key = { item . member . id }
143+ key = { item . member ?. id ?? item . id }
97144 onClick = { ( ) => handleRowClick ( item ) }
98145 >
99146 { ( columnKey ) => < TableCell > { renderCell ( item , columnKey ) } </ TableCell > }
0 commit comments