1
- import { ChangeEvent , useState , KeyboardEvent } from 'react' ;
1
+ 'use client' ;
2
+ import { ChangeEvent , useState , useEffect } from 'react' ;
2
3
import InfiniteScroll from 'react-infinite-scroller' ;
4
+ import Link from 'next/link' ;
3
5
import Image from 'next/image' ;
6
+ import { useParams } from 'next/navigation' ;
7
+ import MaterialForm from './MaterialForm' ;
4
8
import MaterialList from './MaterialList' ;
5
9
import getMaterial from '@/src/api/material/getMaterial' ;
6
10
import searchMaterial from '@/src/api/material/searchMaterial' ;
7
- import { Material , ParamsProps } from '@/src/interfaces/navbar' ;
11
+ import useDebounce from '@/src/hooks/useDebounce' ;
12
+ import { Material } from '@/src/interfaces/navbar' ;
8
13
import icons from '@/public/svgs/navbar' ;
9
14
10
- const MaterialContainer = ( {
11
- params,
12
- cId,
13
- } : {
14
- params : ParamsProps ;
15
- cId : string | null ;
16
- } ) => {
15
+ const MaterialContainer = ( ) => {
17
16
const [ materials , setMaterials ] = useState < Material [ ] > ( [ ] ) ;
18
17
const [ searchMaterials , setSearchMaterials ] = useState < Material [ ] > ( [ ] ) ;
19
18
const [ keyWord , setKeyWord ] = useState < string > ( '' ) ;
20
19
const [ boardPage , setBoardPage ] = useState < number > ( 1 ) ;
21
20
const [ hasMore , setHasMore ] = useState < boolean > ( true ) ;
21
+ const [ isOpen , setIsOpen ] = useState < boolean > ( false ) ;
22
+ const param = useParams < { cId : string ; mId : string } > ( ) ;
23
+
24
+ const debounceVal = useDebounce ( keyWord , 500 ) ;
25
+
26
+ useEffect ( ( ) => {
27
+ if ( debounceVal ) {
28
+ searchMaterial ( parseInt ( param . cId ) , debounceVal , 1 , 5 ) . then ( res => {
29
+ setSearchMaterials ( res ) ;
30
+ } ) ;
31
+ }
32
+ } , [ debounceVal ] ) ;
22
33
23
34
const onLoadMore = ( ) => {
24
35
setHasMore ( false ) ;
25
- getMaterial ( 4 , boardPage , 8 ) . then ( res => {
36
+ getMaterial ( parseInt ( param . cId ) , boardPage , 8 ) . then ( res => {
26
37
if ( res . length === 0 ) {
27
38
setHasMore ( false ) ;
28
39
} else {
@@ -46,56 +57,73 @@ const MaterialContainer = ({
46
57
}
47
58
} ;
48
59
49
- const handleKeyEnter = ( e : KeyboardEvent < HTMLInputElement > ) => {
50
- if ( e . key === 'Enter' )
51
- searchMaterial ( 1 , keyWord , 1 , 5 ) . then ( res => {
52
- console . log ( res ) ;
53
- setSearchMaterials ( res ) ;
54
- } ) ;
55
- } ;
56
-
57
60
return (
58
- < div className = "" >
59
- { /* prompt - search */ }
60
- < div className = "w-full flex bg-white items-center mb-3 px-1" >
61
- < Image
62
- src = { icons . search }
63
- alt = "icon"
64
- width = { 20 }
65
- height = { 20 }
66
- className = "w-5 h-5 opacity-50"
67
- />
68
- < input
69
- type = "text"
70
- className = "w-full p-1 border-0 outline-none"
71
- placeholder = "검색"
72
- onChange = { handleInputText }
73
- onKeyDown = { handleKeyEnter }
74
- />
75
- </ div >
76
- { /* Prompt - list */ }
77
- < div className = "h-[350px] overflow-auto" >
78
- < InfiniteScroll
79
- pageStart = { 0 }
80
- loadMore = { onLoadMore }
81
- hasMore = { hasMore }
82
- loader = { < div key = "unique" > loading...</ div > }
83
- useWindow = { false }
84
- threshold = { 20 }
85
- >
86
- { materials ? (
87
- keyWord ? (
88
- < MaterialList
89
- materials = { searchMaterials }
90
- params = { params }
91
- cId = { cId }
61
+ < div className = "h-full flex flex-col" >
62
+ { param . cId && (
63
+ < >
64
+ < div className = "w-full flex-1" >
65
+ < div className = "w-full flex justify-between items-center mb-4" >
66
+ < p className = "text-zinc-400" > 자료</ p >
67
+ < div
68
+ className = "text-end bg-blue-500 w-6 h-6 flex justify-center items-center rounded-lg"
69
+ onClick = { ( ) => setIsOpen ( true ) }
70
+ >
71
+ < Image src = { icons . plus } width = { 30 } height = { 30 } alt = "plus" />
72
+ </ div >
73
+ </ div >
74
+ { isOpen && < MaterialForm setIsOpen = { setIsOpen } cId = { param . cId } /> }
75
+ { /* prompt - search */ }
76
+ < div className = "w-full flex bg-white items-center mb-3 px-1" >
77
+ < Image
78
+ src = { icons . search }
79
+ alt = "icon"
80
+ width = { 20 }
81
+ height = { 20 }
82
+ className = "w-5 h-5 opacity-50"
83
+ />
84
+ < input
85
+ type = "text"
86
+ className = "w-full p-1 border-0 outline-none"
87
+ placeholder = "Search"
88
+ onChange = { handleInputText }
92
89
/>
90
+ </ div >
91
+ { /* Prompt - list */ }
92
+ < div className = "h-[calc(100%-85px)] overflow-auto" >
93
+ < InfiniteScroll
94
+ pageStart = { 0 }
95
+ loadMore = { onLoadMore }
96
+ hasMore = { hasMore }
97
+ loader = { < div key = "unique" > loading...</ div > }
98
+ useWindow = { false }
99
+ threshold = { 20 }
100
+ >
101
+ { materials && keyWord ? (
102
+ < MaterialList materials = { searchMaterials } cId = { param . cId } />
103
+ ) : (
104
+ < MaterialList materials = { materials } cId = { param . cId } />
105
+ ) }
106
+ </ InfiniteScroll >
107
+ </ div >
108
+ </ div >
109
+ < div className = "flex-none h-16" > </ div >
110
+ { /* Exit */ }
111
+ < div className = "flex flex-none h-[50px]" >
112
+ < Image
113
+ src = { icons . door }
114
+ alt = "icon"
115
+ width = { 30 }
116
+ height = { 30 }
117
+ className = "w-6 h-6 mr-2"
118
+ > </ Image >
119
+ { param . mId ? (
120
+ < Link href = { `/classes/${ param . cId } ` } > 프롬프트 떠나기</ Link >
93
121
) : (
94
- < MaterialList materials = { materials } params = { params } cId = { cId } / >
95
- )
96
- ) : null }
97
- </ InfiniteScroll >
98
- </ div >
122
+ < Link href = "/classes" > 클래스 떠나기 </ Link >
123
+ ) }
124
+ </ div >
125
+ </ >
126
+ ) }
99
127
</ div >
100
128
) ;
101
129
} ;
0 commit comments