@@ -80,6 +80,13 @@ const EntityTable: React.FC<EntityTableProps> = ({
8080 const [ isAddingItem , setIsAddingItem ] = useState ( false ) ;
8181 const [ colorPickerOpen , setColorPickerOpen ] = useState < number | null > ( null ) ;
8282 const [ openMenuId , setOpenMenuId ] = useState < number | null > ( null ) ;
83+ const [ isDisplayFieldManuallyEdited , setIsDisplayFieldManuallyEdited ] =
84+ useState ( false ) ;
85+ const [
86+ isNewItemDisplayFieldManuallyEdited ,
87+ setIsNewItemDisplayFieldManuallyEdited ,
88+ ] = useState ( false ) ;
89+
8390 const [ newItem , setNewItem ] = useState < EntityTableItem > ( {
8491 id : 0 ,
8592 name : '' ,
@@ -129,6 +136,21 @@ const EntityTable: React.FC<EntityTableProps> = ({
129136 const handleEditItem = ( item : EntityTableItem ) => {
130137 setEditingItem ( item ) ;
131138 setOpenMenuId ( null ) ;
139+
140+ // Check if abbreviation is custom (different from name prefix)
141+ const namePrefix = generateAbbreviationPrefix (
142+ item . name ,
143+ maxAbbreviationLength
144+ ) ;
145+ const hasCustomAbbreviation = item . abbreviation !== namePrefix ;
146+
147+ // Only auto-update if abbreviation isn't custom
148+ setIsDisplayFieldManuallyEdited ( hasCustomAbbreviation ) ;
149+ } ;
150+
151+ // Calculate prefix for abbreviation (display) field
152+ const generateAbbreviationPrefix = ( name : string , maxLength : number ) => {
153+ return name . trim ( ) . substring ( 0 , maxLength ) ;
132154 } ;
133155
134156 const handleSaveEditedItem = ( ) => {
@@ -150,8 +172,17 @@ const EntityTable: React.FC<EntityTableProps> = ({
150172 return ;
151173 }
152174
153- // Store the current editing state
175+ // If abbreviation is empty, set it to the name prefix
154176 const currentEditingItem = { ...editingItem } ;
177+ if (
178+ ! currentEditingItem . abbreviation ||
179+ currentEditingItem . abbreviation . trim ( ) === ''
180+ ) {
181+ currentEditingItem . abbreviation = generateAbbreviationPrefix (
182+ currentEditingItem . name ,
183+ maxAbbreviationLength
184+ ) ;
185+ }
155186
156187 // Reset the editing state
157188 setEditingItem ( null ) ;
@@ -194,11 +225,14 @@ const EntityTable: React.FC<EntityTableProps> = ({
194225 return ;
195226 }
196227
197- // Create a temporary item with the new data
198- const itemToAdd = {
199- ...newItem ,
200- id : 0 , // This will be replaced with a negative ID by the change management hook
201- } ;
228+ // If abbreviation is empty, set it to the name prefix
229+ const itemToAdd = { ...newItem } ;
230+ if ( ! itemToAdd . abbreviation || itemToAdd . abbreviation . trim ( ) === '' ) {
231+ itemToAdd . abbreviation = generateAbbreviationPrefix (
232+ itemToAdd . name ,
233+ maxAbbreviationLength
234+ ) ;
235+ }
202236
203237 // Reset form and close it
204238 handleUpdateEntity ( itemToAdd ) ;
@@ -223,6 +257,8 @@ const EntityTable: React.FC<EntityTableProps> = ({
223257 setEditingItem ( null ) ;
224258 setIsAddingItem ( false ) ;
225259 setColorPickerOpen ( null ) ;
260+ setIsDisplayFieldManuallyEdited ( false ) ;
261+ setIsNewItemDisplayFieldManuallyEdited ( false ) ;
226262 } ;
227263
228264 const handleArchiveItem = ( item : EntityTableItem ) => {
@@ -463,12 +499,22 @@ const EntityTable: React.FC<EntityTableProps> = ({
463499 ) }
464500 < Input
465501 value = { editingItem . name }
466- onChange = { ( e ) =>
502+ onChange = { ( e ) => {
503+ const newName = e . target . value ;
504+ // Auto-generate abbreviation if not manually edited
505+ const newAbbreviation = ! isDisplayFieldManuallyEdited
506+ ? generateAbbreviationPrefix (
507+ newName ,
508+ maxAbbreviationLength
509+ )
510+ : editingItem . abbreviation ;
511+
467512 setEditingItem ( {
468513 ...editingItem ,
469- name : e . target . value ,
470- } )
471- }
514+ name : newName ,
515+ abbreviation : newAbbreviation ,
516+ } ) ;
517+ } }
472518 size = "sm"
473519 flex = "1"
474520 maxLength = { maxFullNameLength }
@@ -484,12 +530,35 @@ const EntityTable: React.FC<EntityTableProps> = ({
484530 >
485531 < Input
486532 value = { editingItem . abbreviation }
487- onChange = { ( e ) =>
533+ onChange = { ( e ) => {
534+ const newValue = e . target . value ;
535+ // If the field is cleared, turn off manual edit mode to allow auto-updating again
536+ if ( ! newValue || newValue . trim ( ) === '' ) {
537+ setIsDisplayFieldManuallyEdited ( false ) ;
538+ } else {
539+ setIsDisplayFieldManuallyEdited ( true ) ;
540+ }
541+
488542 setEditingItem ( {
489543 ...editingItem ,
490- abbreviation : e . target . value ,
491- } )
492- }
544+ abbreviation : newValue ,
545+ } ) ;
546+ } }
547+ onBlur = { ( ) => {
548+ // If the display field is empty when it loses focus, immediately fill it
549+ if (
550+ ! editingItem . abbreviation ||
551+ editingItem . abbreviation . trim ( ) === ''
552+ ) {
553+ setEditingItem ( {
554+ ...editingItem ,
555+ abbreviation : generateAbbreviationPrefix (
556+ editingItem . name ,
557+ maxAbbreviationLength
558+ ) ,
559+ } ) ;
560+ }
561+ } }
493562 size = "sm"
494563 maxW = "60px"
495564 maxLength = { maxAbbreviationLength }
@@ -809,12 +878,19 @@ const EntityTable: React.FC<EntityTableProps> = ({
809878 ) }
810879 < Input
811880 value = { newItem . name }
812- onChange = { ( e ) =>
881+ onChange = { ( e ) => {
882+ const newName = e . target . value ;
883+ // Auto-generate abbreviation if not manually edited
884+ const newAbbreviation = ! isNewItemDisplayFieldManuallyEdited
885+ ? generateAbbreviationPrefix ( newName , maxAbbreviationLength )
886+ : newItem . abbreviation ;
887+
813888 setNewItem ( {
814889 ...newItem ,
815- name : e . target . value ,
816- } )
817- }
890+ name : newName ,
891+ abbreviation : newAbbreviation ,
892+ } ) ;
893+ } }
818894 placeholder = { `${ title } name` }
819895 size = "sm"
820896 flex = "1"
@@ -831,12 +907,35 @@ const EntityTable: React.FC<EntityTableProps> = ({
831907 >
832908 < Input
833909 value = { newItem . abbreviation }
834- onChange = { ( e ) =>
910+ onChange = { ( e ) => {
911+ const newValue = e . target . value ;
912+ // If the field is cleared, turn off manual edit mode to allow auto-updating again
913+ if ( ! newValue || newValue . trim ( ) === '' ) {
914+ setIsNewItemDisplayFieldManuallyEdited ( false ) ;
915+ } else {
916+ setIsNewItemDisplayFieldManuallyEdited ( true ) ;
917+ }
918+
835919 setNewItem ( {
836920 ...newItem ,
837- abbreviation : e . target . value ,
838- } )
839- }
921+ abbreviation : newValue ,
922+ } ) ;
923+ } }
924+ onBlur = { ( ) => {
925+ // If the display field is empty when it loses focus, immediately fill it
926+ if (
927+ ! newItem . abbreviation ||
928+ newItem . abbreviation . trim ( ) === ''
929+ ) {
930+ setNewItem ( {
931+ ...newItem ,
932+ abbreviation : generateAbbreviationPrefix (
933+ newItem . name ,
934+ maxAbbreviationLength
935+ ) ,
936+ } ) ;
937+ }
938+ } }
840939 placeholder = "Abbr."
841940 size = "sm"
842941 maxW = "60px"
@@ -872,7 +971,11 @@ const EntityTable: React.FC<EntityTableProps> = ({
872971 < Box
873972 as = "button"
874973 width = "100%"
875- onClick = { ( ) => setIsAddingItem ( true ) }
974+ onClick = { ( ) => {
975+ setIsAddingItem ( true ) ;
976+ // Reset the new item manually edited flag when starting to add a new item
977+ setIsNewItemDisplayFieldManuallyEdited ( false ) ;
978+ } }
876979 _hover = { { bg : 'neutralGray.100' } }
877980 transition = "background-color 0.2s ease"
878981 textAlign = "left"
0 commit comments