11'use client'
22
3- import { useState } from 'react'
3+ import { useEffect , useState } from 'react'
44import { ChevronDown , Info , Plus , X } from 'lucide-react'
55import {
66 Badge ,
@@ -30,6 +30,7 @@ import { createLogger } from '@/lib/logs/console/logger'
3030import { useKnowledgeBaseTagDefinitions } from '@/hooks/use-knowledge-base-tag-definitions'
3131import { useNextAvailableSlot } from '@/hooks/use-next-available-slot'
3232import { type TagDefinitionInput , useTagDefinitions } from '@/hooks/use-tag-definitions'
33+ import { TypedTagInput } from '../tag-input/typed-tag-input'
3334
3435const logger = createLogger ( 'DocumentTagEntry' )
3536
@@ -66,6 +67,43 @@ export function DocumentTagEntry({
6667 const { saveTagDefinitions } = documentTagHook
6768 const { tagDefinitions : kbTagDefinitions , fetchTagDefinitions : refreshTagDefinitions } = kbTagHook
6869
70+ // State for field types
71+ const [ fieldTypes , setFieldTypes ] = useState <
72+ Array < {
73+ value : string
74+ label : string
75+ description : string
76+ placeholder : string
77+ } >
78+ > ( [
79+ {
80+ value : 'text' ,
81+ label : 'Text' ,
82+ description : 'Free-form text content' ,
83+ placeholder : 'Enter text' ,
84+ } ,
85+ ] )
86+
87+ // Fetch field types on component mount
88+ useEffect ( ( ) => {
89+ const fetchFieldTypes = async ( ) => {
90+ try {
91+ const response = await fetch ( '/api/knowledge/field-types' )
92+ if ( response . ok ) {
93+ const result = await response . json ( )
94+ if ( result . success ) {
95+ setFieldTypes ( result . data . fieldTypes )
96+ }
97+ }
98+ } catch ( error ) {
99+ logger . error ( 'Error fetching field types:' , error )
100+ // Keep the default fallback
101+ }
102+ }
103+
104+ fetchFieldTypes ( )
105+ } , [ ] )
106+
69107 // Modal state for tag editing
70108 const [ editingTagIndex , setEditingTagIndex ] = useState < number | null > ( null )
71109 const [ modalOpen , setModalOpen ] = useState ( false )
@@ -363,16 +401,23 @@ export function DocumentTagEntry({
363401 value = { editForm . displayName }
364402 onChange = { ( e ) => setEditForm ( { ...editForm , displayName : e . target . value } ) }
365403 placeholder = 'Enter tag name'
366- className = 'flex-1 '
404+ className = 'h-8 w-full rounded-[10px] border-[#E5E5E5] bg-[#FFFFFF] text-sm dark:border-[#414141] dark:bg-[var(--surface-elevated)] '
367405 />
368406 { editingTagIndex === null && availableDefinitions . length > 0 && (
369407 < DropdownMenu >
370408 < DropdownMenuTrigger asChild >
371- < Button variant = 'outline' size = 'sm' >
409+ < Button
410+ variant = 'outline'
411+ size = 'sm'
412+ className = 'h-8 rounded-[10px] border-[#E5E5E5] bg-[#FFFFFF] dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
413+ >
372414 < ChevronDown className = 'h-4 w-4' />
373415 </ Button >
374416 </ DropdownMenuTrigger >
375- < DropdownMenuContent align = 'end' >
417+ < DropdownMenuContent
418+ align = 'end'
419+ className = 'w-[240px] rounded-lg border-[#E5E5E5] bg-[#FFFFFF] p-0 shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]'
420+ >
376421 { availableDefinitions . map ( ( def ) => (
377422 < DropdownMenuItem
378423 key = { def . id }
@@ -383,8 +428,13 @@ export function DocumentTagEntry({
383428 fieldType : def . fieldType ,
384429 } )
385430 }
431+ className = 'flex cursor-pointer items-center justify-between rounded-md px-3 py-2 font-[380] text-card-foreground text-sm hover:bg-secondary/50 focus:bg-secondary/50'
386432 >
387- { def . displayName }
433+ < span className = 'truncate' > { def . displayName } </ span >
434+ < span className = 'ml-2 shrink-0 text-muted-foreground text-xs' >
435+ { fieldTypes . find ( ( ft ) => ft . value === def . fieldType ) ?. label ||
436+ def . fieldType }
437+ </ span >
388438 </ DropdownMenuItem >
389439 ) ) }
390440 </ DropdownMenuContent >
@@ -399,25 +449,48 @@ export function DocumentTagEntry({
399449 < Select
400450 value = { editForm . fieldType }
401451 onValueChange = { ( value ) => setEditForm ( { ...editForm , fieldType : value } ) }
402- disabled = { editingTagIndex !== null } // Disable in edit mode
452+ disabled = {
453+ editingTagIndex !== null || // Disable in edit mode
454+ ( editingTagIndex === null &&
455+ kbTagDefinitions . some (
456+ ( def ) => def . displayName . toLowerCase ( ) === editForm . displayName . toLowerCase ( )
457+ ) )
458+ } // Also disable when using existing definition in create mode
403459 >
404- < SelectTrigger >
405- < SelectValue />
460+ < SelectTrigger className = 'h-8 w-full justify-between rounded-[10px] border-[#E5E5E5] bg-[#FFFFFF] text-sm dark:border-[#414141] dark:bg-[var(--surface-elevated)]' >
461+ < SelectValue placeholder = 'Select type' />
406462 </ SelectTrigger >
407- < SelectContent >
408- < SelectItem value = 'text' > Text</ SelectItem >
463+ < SelectContent className = 'rounded-lg border-[#E5E5E5] bg-[#FFFFFF] dark:border-[#414141] dark:bg-[var(--surface-elevated)]' >
464+ { fieldTypes . map ( ( fieldType ) => (
465+ < SelectItem key = { fieldType . value } value = { fieldType . value } className = 'text-sm' >
466+ { fieldType . label }
467+ </ SelectItem >
468+ ) ) }
409469 </ SelectContent >
410470 </ Select >
411471 </ div >
412472
413473 { /* Tag Value */ }
414474 < div className = 'space-y-2' >
415475 < Label htmlFor = 'tag-value' > Value</ Label >
416- < Input
417- id = 'tag-value'
476+ < TypedTagInput
477+ fieldType = { editForm . fieldType }
418478 value = { editForm . value }
419- onChange = { ( e ) => setEditForm ( { ...editForm , value : e . target . value } ) }
420- placeholder = 'Enter tag value'
479+ onChange = { ( value ) => setEditForm ( { ...editForm , value } ) }
480+ placeholder = {
481+ fieldTypes . find ( ( ft ) => ft . value === editForm . fieldType ) ?. placeholder ||
482+ 'Enter tag value'
483+ }
484+ showInlineError = { true }
485+ onValidityChange = { ( valid ) => {
486+ // Disable save when invalid
487+ // We just store validity in state via a refactor-free approach by toggling a hidden flag on form
488+ // Use a no-op set to trigger re-render when invalid so button disabled reflects it
489+ if ( ! valid ) {
490+ // noop – re-render by updating same state value
491+ setEditForm ( ( prev ) => ( { ...prev } ) )
492+ }
493+ } }
421494 />
422495 </ div >
423496 </ div >
0 commit comments