@@ -22,10 +22,10 @@ import {
2222 type TagDefinition ,
2323 useKnowledgeBaseTagDefinitions ,
2424} from '@/hooks/kb/use-knowledge-base-tag-definitions'
25+ import { useCreateTagDefinition , useDeleteTagDefinition } from '@/hooks/queries/knowledge'
2526
2627const logger = createLogger ( 'BaseTagsModal' )
2728
28- /** Field type display labels */
2929const FIELD_TYPE_LABELS : Record < string , string > = {
3030 text : 'Text' ,
3131 number : 'Number' ,
@@ -45,7 +45,6 @@ interface DocumentListProps {
4545 totalCount : number
4646}
4747
48- /** Displays a list of documents affected by tag operations */
4948function DocumentList ( { documents, totalCount } : DocumentListProps ) {
5049 const displayLimit = 5
5150 const hasMore = totalCount > displayLimit
@@ -95,13 +94,14 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM
9594 const { tagDefinitions : kbTagDefinitions , fetchTagDefinitions : refreshTagDefinitions } =
9695 useKnowledgeBaseTagDefinitions ( knowledgeBaseId )
9796
97+ const createTagMutation = useCreateTagDefinition ( )
98+ const deleteTagMutation = useDeleteTagDefinition ( )
99+
98100 const [ deleteTagDialogOpen , setDeleteTagDialogOpen ] = useState ( false )
99101 const [ selectedTag , setSelectedTag ] = useState < TagDefinition | null > ( null )
100102 const [ viewDocumentsDialogOpen , setViewDocumentsDialogOpen ] = useState ( false )
101- const [ isDeletingTag , setIsDeletingTag ] = useState ( false )
102103 const [ tagUsageData , setTagUsageData ] = useState < TagUsageData [ ] > ( [ ] )
103104 const [ isCreatingTag , setIsCreatingTag ] = useState ( false )
104- const [ isSavingTag , setIsSavingTag ] = useState ( false )
105105 const [ createTagForm , setCreateTagForm ] = useState ( {
106106 displayName : '' ,
107107 fieldType : 'text' ,
@@ -177,27 +177,24 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM
177177 }
178178
179179 const tagNameConflict =
180- isCreatingTag && ! isSavingTag && hasTagNameConflict ( createTagForm . displayName )
180+ isCreatingTag && ! createTagMutation . isPending && hasTagNameConflict ( createTagForm . displayName )
181181
182182 const canSaveTag = ( ) => {
183183 return createTagForm . displayName . trim ( ) && ! hasTagNameConflict ( createTagForm . displayName )
184184 }
185185
186- /** Get slot usage counts per field type */
187186 const getSlotUsageByFieldType = ( fieldType : string ) : { used : number ; max : number } => {
188187 const config = TAG_SLOT_CONFIG [ fieldType as keyof typeof TAG_SLOT_CONFIG ]
189188 if ( ! config ) return { used : 0 , max : 0 }
190189 const used = kbTagDefinitions . filter ( ( def ) => def . fieldType === fieldType ) . length
191190 return { used, max : config . maxSlots }
192191 }
193192
194- /** Check if a field type has available slots */
195193 const hasAvailableSlots = ( fieldType : string ) : boolean => {
196194 const { used, max } = getSlotUsageByFieldType ( fieldType )
197195 return used < max
198196 }
199197
200- /** Field type options for Combobox */
201198 const fieldTypeOptions : ComboboxOption [ ] = useMemo ( ( ) => {
202199 return SUPPORTED_FIELD_TYPES . filter ( ( type ) => hasAvailableSlots ( type ) ) . map ( ( type ) => {
203200 const { used, max } = getSlotUsageByFieldType ( type )
@@ -211,43 +208,17 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM
211208 const saveTagDefinition = async ( ) => {
212209 if ( ! canSaveTag ( ) ) return
213210
214- setIsSavingTag ( true )
215211 try {
216- // Check if selected field type has available slots
217212 if ( ! hasAvailableSlots ( createTagForm . fieldType ) ) {
218213 throw new Error ( `No available slots for ${ createTagForm . fieldType } type` )
219214 }
220215
221- // Get the next available slot from the API
222- const slotResponse = await fetch (
223- `/api/knowledge/${ knowledgeBaseId } /next-available-slot?fieldType=${ createTagForm . fieldType } `
224- )
225- if ( ! slotResponse . ok ) {
226- throw new Error ( 'Failed to get available slot' )
227- }
228- const slotResult = await slotResponse . json ( )
229- if ( ! slotResult . success || ! slotResult . data ?. nextAvailableSlot ) {
230- throw new Error ( 'No available tag slots for this field type' )
231- }
232-
233- const newTagDefinition = {
234- tagSlot : slotResult . data . nextAvailableSlot ,
216+ await createTagMutation . mutateAsync ( {
217+ knowledgeBaseId,
235218 displayName : createTagForm . displayName . trim ( ) ,
236219 fieldType : createTagForm . fieldType ,
237- }
238-
239- const response = await fetch ( `/api/knowledge/${ knowledgeBaseId } /tag-definitions` , {
240- method : 'POST' ,
241- headers : {
242- 'Content-Type' : 'application/json' ,
243- } ,
244- body : JSON . stringify ( newTagDefinition ) ,
245220 } )
246221
247- if ( ! response . ok ) {
248- throw new Error ( 'Failed to create tag definition' )
249- }
250-
251222 await Promise . all ( [ refreshTagDefinitions ( ) , fetchTagUsage ( ) ] )
252223
253224 setCreateTagForm ( {
@@ -257,36 +228,24 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM
257228 setIsCreatingTag ( false )
258229 } catch ( error ) {
259230 logger . error ( 'Error creating tag definition:' , error )
260- } finally {
261- setIsSavingTag ( false )
262231 }
263232 }
264233
265234 const confirmDeleteTag = async ( ) => {
266235 if ( ! selectedTag ) return
267236
268- setIsDeletingTag ( true )
269237 try {
270- const response = await fetch (
271- `/api/knowledge/${ knowledgeBaseId } /tag-definitions/${ selectedTag . id } ` ,
272- {
273- method : 'DELETE' ,
274- }
275- )
276-
277- if ( ! response . ok ) {
278- const errorText = await response . text ( )
279- throw new Error ( `Failed to delete tag definition: ${ response . status } ${ errorText } ` )
280- }
238+ await deleteTagMutation . mutateAsync ( {
239+ knowledgeBaseId,
240+ tagDefinitionId : selectedTag . id ,
241+ } )
281242
282243 await Promise . all ( [ refreshTagDefinitions ( ) , fetchTagUsage ( ) ] )
283244
284245 setDeleteTagDialogOpen ( false )
285246 setSelectedTag ( null )
286247 } catch ( error ) {
287248 logger . error ( 'Error deleting tag definition:' , error )
288- } finally {
289- setIsDeletingTag ( false )
290249 }
291250 }
292251
@@ -433,11 +392,11 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM
433392 className = 'flex-1'
434393 disabled = {
435394 ! canSaveTag ( ) ||
436- isSavingTag ||
395+ createTagMutation . isPending ||
437396 ! hasAvailableSlots ( createTagForm . fieldType )
438397 }
439398 >
440- { isSavingTag ? 'Creating...' : 'Create Tag' }
399+ { createTagMutation . isPending ? 'Creating...' : 'Create Tag' }
441400 </ Button >
442401 </ div >
443402 </ div >
@@ -481,13 +440,17 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM
481440 < ModalFooter >
482441 < Button
483442 variant = 'default'
484- disabled = { isDeletingTag }
443+ disabled = { deleteTagMutation . isPending }
485444 onClick = { ( ) => setDeleteTagDialogOpen ( false ) }
486445 >
487446 Cancel
488447 </ Button >
489- < Button variant = 'destructive' onClick = { confirmDeleteTag } disabled = { isDeletingTag } >
490- { isDeletingTag ? < > Deleting...</ > : 'Delete Tag' }
448+ < Button
449+ variant = 'destructive'
450+ onClick = { confirmDeleteTag }
451+ disabled = { deleteTagMutation . isPending }
452+ >
453+ { deleteTagMutation . isPending ? 'Deleting...' : 'Delete Tag' }
491454 </ Button >
492455 </ ModalFooter >
493456 </ ModalContent >
0 commit comments