1
- // TagCard.tsx
2
1
"use client" ;
3
2
import CardTag from "@/components/tags/card-tag" ;
4
3
import { getTags } from "@/components/tags/hooks/get-tags" ;
@@ -31,13 +30,16 @@ export const TagCard = ({ type }: TagCardProps) => {
31
30
const ws = useRef < WebSocket | null > ( null ) ;
32
31
const [ tags , setTags ] = useState < TagType [ ] > ( [ ] ) ;
33
32
const [ aiRecommendedTags , setAiRecommendedTags ] = useState < TagType [ ] > ( [ ] ) ;
34
- const [ selectedTags , setSelectedTags ] = useState < Set < number > > ( new Set ( ) ) ;
33
+ const [ selectedRegularTags , setSelectedRegularTags ] = useState < Set < number > > ( new Set ( ) ) ;
34
+ const [ selectedAiTags , setSelectedAiTags ] = useState < Set < number > > ( new Set ( ) ) ;
35
35
const [ isLoading , setIsLoading ] = useState ( true ) ;
36
36
const [ error , setError ] = useState < string | null > ( null ) ;
37
37
const [ currentUser ] = useAtom ( userAtom ) ;
38
38
const [ currentCommunity ] = useAtom ( communityAtom ) ;
39
39
const [ searchQuery , setSearchQuery ] = useState ( "" ) ;
40
40
41
+ const totalSelectedTags = new Set ( [ ...selectedRegularTags , ...selectedAiTags ] ) ;
42
+
41
43
const filteredTags = tags . filter ( tag =>
42
44
tag . name . toLowerCase ( ) . includes ( searchQuery . toLowerCase ( ) )
43
45
) ;
@@ -133,23 +135,52 @@ export const TagCard = ({ type }: TagCardProps) => {
133
135
} , [ type , currentUser ?. uuid , currentCommunity ?. uuid ] ) ;
134
136
135
137
const handleTagClick = ( index : number , isAiTag : boolean = false ) => {
136
- setSelectedTags ( prev => {
137
- const newSet = new Set ( prev ) ;
138
- if ( newSet . has ( index ) ) {
139
- newSet . delete ( index ) ;
140
- } else {
141
- newSet . add ( index ) ;
138
+ if ( isAiTag ) {
139
+ const aiTag = aiRecommendedTags [ index ] ;
140
+ const regularTagIndex = tags . findIndex ( tag => tag . name === aiTag . name ) ;
142
141
143
- if ( ws . current ?. readyState === WebSocket . OPEN ) {
144
- const tagName = isAiTag ? aiRecommendedTags [ index ] . name : tags [ index ] . name ;
145
- const message = {
146
- tag : tagName ,
147
- } ;
148
- ws . current . send ( JSON . stringify ( message ) ) ;
142
+ setSelectedAiTags ( prev => {
143
+ const newSet = new Set ( prev ) ;
144
+ if ( newSet . has ( index ) ) {
145
+ newSet . delete ( index ) ;
146
+ if ( regularTagIndex !== - 1 ) {
147
+ setSelectedRegularTags ( prevRegular => {
148
+ const newRegularSet = new Set ( prevRegular ) ;
149
+ newRegularSet . delete ( regularTagIndex ) ;
150
+ return newRegularSet ;
151
+ } ) ;
152
+ }
153
+ } else {
154
+ newSet . add ( index ) ;
155
+ if ( regularTagIndex !== - 1 ) {
156
+ setSelectedRegularTags ( prevRegular => {
157
+ const newRegularSet = new Set ( prevRegular ) ;
158
+ newRegularSet . add ( regularTagIndex ) ;
159
+ return newRegularSet ;
160
+ } ) ;
161
+ }
149
162
}
150
- }
151
- return newSet ;
152
- } ) ;
163
+ return newSet ;
164
+ } ) ;
165
+ } else {
166
+ setSelectedRegularTags ( prev => {
167
+ const newSet = new Set ( prev ) ;
168
+ if ( newSet . has ( index ) ) {
169
+ newSet . delete ( index ) ;
170
+ } else {
171
+ newSet . add ( index ) ;
172
+ }
173
+ return newSet ;
174
+ } ) ;
175
+ }
176
+
177
+ if ( ws . current ?. readyState === WebSocket . OPEN ) {
178
+ const tagName = isAiTag ? aiRecommendedTags [ index ] . name : tags [ index ] . name ;
179
+ const message = {
180
+ tag : tagName ,
181
+ } ;
182
+ ws . current . send ( JSON . stringify ( message ) ) ;
183
+ }
153
184
} ;
154
185
155
186
const onClick = async ( ) => {
@@ -172,14 +203,15 @@ export const TagCard = ({ type }: TagCardProps) => {
172
203
return ;
173
204
}
174
205
175
- if ( selectedTags . size < 1 ) {
206
+ if ( totalSelectedTags . size < 1 ) {
176
207
alert ( "1つ以上のタグを選択してください" ) ;
177
208
return ;
178
209
}
179
210
180
- const selectedTagNames = Array . from ( selectedTags ) . map ( index => (
181
- tags [ index ] ?. name || aiRecommendedTags [ index ] ?. name
182
- ) ) . filter ( Boolean ) ;
211
+ const selectedTagNames = [
212
+ ...Array . from ( selectedRegularTags ) . map ( index => tags [ index ] ?. name ) ,
213
+ ...Array . from ( selectedAiTags ) . map ( index => aiRecommendedTags [ index ] ?. name )
214
+ ] . filter ( Boolean ) ;
183
215
184
216
try {
185
217
if ( ws . current ) {
@@ -212,13 +244,13 @@ export const TagCard = ({ type }: TagCardProps) => {
212
244
searchQuery = { searchQuery }
213
245
setSearchQuery = { setSearchQuery }
214
246
/>
215
- < ScrollArea className = "w-full whitespace-nowrap rounded-md border" >
247
+ < ScrollArea className = "w-full h-[120px] whitespace-nowrap rounded-md border" >
216
248
< div className = { style . tagContainer } >
217
249
{ filteredTags . map ( ( tag , index ) => (
218
250
< CardTag
219
251
key = { index }
220
252
variant = { tag . color }
221
- className = { `${ selectedTags . has ( index ) ? style . selected : "" } ` }
253
+ className = { `${ selectedRegularTags . has ( index ) ? style . selected : "" } ` }
222
254
onClick = { ( ) => handleTagClick ( index ) }
223
255
>
224
256
{ tag . name }
@@ -238,7 +270,7 @@ export const TagCard = ({ type }: TagCardProps) => {
238
270
< CardTag
239
271
key = { `ai-recommended-${ index } ` }
240
272
variant = { tag . color }
241
- className = { `${ selectedTags . has ( index ) ? style . selected : "" } ${ style . aiTag } ` }
273
+ className = { `${ selectedAiTags . has ( index ) ? style . selected : "" } ${ style . aiTag } ` }
242
274
onClick = { ( ) => handleTagClick ( index , true ) }
243
275
>
244
276
{ tag . name }
@@ -249,10 +281,10 @@ export const TagCard = ({ type }: TagCardProps) => {
249
281
) }
250
282
</ CardContent >
251
283
< CardFooter className = { style . footer } >
252
- < Button onClick = { onClick } className = { style . button } disabled = { selectedTags . size < 1 } >
284
+ < Button onClick = { onClick } className = { style . button } disabled = { totalSelectedTags . size < 1 } >
253
285
これが気に入った!
254
286
</ Button >
255
287
</ CardFooter >
256
288
</ Card >
257
289
) ;
258
- }
290
+ } ;
0 commit comments