@@ -23,8 +23,10 @@ import {
2323 ListItem ,
2424 ListItemText ,
2525 ListItemSecondaryAction ,
26+ InputAdornment ,
27+ Tooltip ,
2628} from '@mui/material' ;
27- import { Add , Delete , Edit , NoteOutlined } from '@mui/icons-material' ;
29+ import { Add , Delete , Edit , NewReleasesOutlined , NoteOutlined } from '@mui/icons-material' ;
2830import { TagGroup , Tag } from '../types' ;
2931
3032interface TagPageProps {
@@ -156,11 +158,6 @@ export function TagPage({
156158 try {
157159 await onAddTag ( selectedGroup . id , newTagName ) ;
158160 setNewTagName ( '' ) ;
159- // Refresh the selected group data
160- const updatedGroup = tagGroups . find ( ( g ) => g . id === selectedGroup . id ) ;
161- if ( updatedGroup ) {
162- setSelectedGroup ( updatedGroup ) ;
163- }
164161 } catch ( err ) {
165162 // eslint-disable-next-line no-console
166163 console . error ( 'Failed to add tag:' , err ) ;
@@ -173,7 +170,7 @@ export function TagPage({
173170 if ( ! selectedGroup || ! onEditTag ) return ;
174171
175172 try {
176- await onEditTag ( selectedGroup . id , tag . name , tagName , tagDescription ) ;
173+ await onEditTag ( selectedGroup . id , tag . id , tagName , tagDescription ) ;
177174 } catch ( err ) {
178175 // eslint-disable-next-line no-console
179176 console . error ( 'Failed to edit tag:' , err ) ;
@@ -185,18 +182,10 @@ export function TagPage({
185182 const handleDeleteTag = async ( tag : Tag ) => {
186183 // eslint-disable-next-line no-alert, no-restricted-globals
187184 if ( ! confirm ( `Delete tag "${ tag . name } "?` ) ) return ;
188-
189185 if ( ! selectedGroup || ! onDeleteTag ) return ;
190186
191187 try {
192- // We need to find the tag ID - for now we're using tag name
193- // The backend API expects tag ID, so we'll need to update this
194- await onDeleteTag ( selectedGroup . id , tag . name ) ;
195- // Refresh the selected group data
196- const updatedGroup = tagGroups . find ( ( g ) => g . id === selectedGroup . id ) ;
197- if ( updatedGroup ) {
198- setSelectedGroup ( updatedGroup ) ;
199- }
188+ await onDeleteTag ( selectedGroup . id , tag . id ) ;
200189 } catch ( err ) {
201190 // eslint-disable-next-line no-console
202191 console . error ( 'Failed to delete tag:' , err ) ;
@@ -329,76 +318,114 @@ export function TagPage({
329318 < Box sx = { { px : 3 , pt : 1 , borderBottom : '1px solid #eee' } } >
330319 < TextField
331320 fullWidth
321+ margin = "normal"
322+ disabled = { ! isAdmin }
332323 label = "Title"
333324 value = { groupName }
334325 onChange = { ( e ) => setGroupName ( e . target . value ) }
335- margin = "normal"
336- disabled = { ! isAdmin }
326+ InputProps = { {
327+ endAdornment : (
328+ < InputAdornment position = "end" >
329+ { editMode && selectedGroup && groupName !== selectedGroup . name && (
330+ < Tooltip title = "Group title has unsaved changes" >
331+ < NewReleasesOutlined color = "warning" />
332+ </ Tooltip >
333+ ) }
334+ </ InputAdornment >
335+ ) ,
336+ } }
337337 />
338338 < TextField
339339 fullWidth
340- label = "Description"
341- value = { groupDescription }
342- onChange = { ( e ) => setGroupDescription ( e . target . value ) }
343340 margin = "normal"
344- disabled = { ! isAdmin }
345341 multiline
346342 rows = { 2 }
347- />
348- </ Box >
349-
350- < Box sx = { { flex : 1 , overflowY : 'auto' , px : 3 } } >
351- { selectedGroup && selectedGroup . tags . length > 0 ? (
352- < List sx = { { p : 0 } } subheader = { < ListSubheader > Tags</ ListSubheader > } >
353- { selectedGroup . tags . map ( ( tag , idx ) => (
354- < ListItem key = { tag . id } divider = { idx < selectedGroup . tags . length - 1 } >
355- < ListItemText
356- primary = { tag . name }
357- secondary = { tag . description }
358- sx = { { pr : 3 , overflow : 'hidden' } }
359- secondaryTypographyProps = { {
360- variant : 'subtitle2' ,
361- style : {
362- whiteSpace : 'nowrap' ,
363- overflow : 'hidden' ,
364- textOverflow : 'ellipsis' ,
365- } ,
366- } }
367- />
368- < ListItemSecondaryAction >
369- { onEditTag && (
370- < IconButton
371- edge = "end"
372- aria-label = "edit tag"
373- size = "small"
374- onClick = { ( ) => handleOpenTagDialog ( tag ) }
375- color = "default"
376- >
377- { isAdmin ? < Edit fontSize = "small" /> : < NoteOutlined fontSize = "small" /> }
378- </ IconButton >
379- ) }
380- { isAdmin && onDeleteTag && (
381- < IconButton
382- edge = "end"
383- aria-label = "delete"
384- size = "small"
385- onClick = { ( ) => handleDeleteTag ( tag ) }
386- color = "error"
387- >
388- < Delete fontSize = "small" />
389- </ IconButton >
343+ disabled = { ! isAdmin }
344+ label = "Description"
345+ value = { groupDescription }
346+ onChange = { ( e ) => setGroupDescription ( e . target . value ) }
347+ InputProps = { {
348+ endAdornment : (
349+ < InputAdornment position = "end" >
350+ { editMode &&
351+ selectedGroup &&
352+ groupDescription !== selectedGroup . description && (
353+ < Tooltip title = "Group description has unsaved changes" >
354+ < NewReleasesOutlined color = "warning" />
355+ </ Tooltip >
390356 ) }
391- </ ListItemSecondaryAction >
392- </ ListItem >
393- ) ) }
394- </ List >
395- ) : (
396- < Typography variant = "body2" color = "text.secondary" sx = { { py : 2 } } >
397- No tags in this group
398- </ Typography >
357+ </ InputAdornment >
358+ ) ,
359+ } }
360+ />
361+ { isAdmin && (
362+ < DialogActions sx = { { px : 0 } } >
363+ < Button onClick = { handleCloseDialog } > Cancel</ Button >
364+ < Button variant = "contained" onClick = { handleSave } >
365+ Save
366+ </ Button >
367+ </ DialogActions >
399368 ) }
400369 </ Box >
401370
371+ { editMode && (
372+ < Box sx = { { flex : 1 , overflowY : 'auto' , px : 3 } } >
373+ { selectedGroup && selectedGroup . tags . length > 0 ? (
374+ < List sx = { { p : 0 } } subheader = { < ListSubheader > Tags</ ListSubheader > } >
375+ { selectedGroup . tags . map ( ( tag , idx ) => (
376+ < ListItem key = { tag . id } divider = { idx < selectedGroup . tags . length - 1 } >
377+ < ListItemText
378+ primary = { tag . name }
379+ secondary = { tag . description }
380+ sx = { { pr : 3 , overflow : 'hidden' } }
381+ secondaryTypographyProps = { {
382+ variant : 'subtitle2' ,
383+ style : {
384+ whiteSpace : 'nowrap' ,
385+ overflow : 'hidden' ,
386+ textOverflow : 'ellipsis' ,
387+ } ,
388+ } }
389+ />
390+ < ListItemSecondaryAction >
391+ { onEditTag && (
392+ < IconButton
393+ edge = "end"
394+ aria-label = "edit tag"
395+ size = "small"
396+ onClick = { ( ) => handleOpenTagDialog ( tag ) }
397+ color = "default"
398+ >
399+ { isAdmin ? (
400+ < Edit fontSize = "small" />
401+ ) : (
402+ < NoteOutlined fontSize = "small" />
403+ ) }
404+ </ IconButton >
405+ ) }
406+ { isAdmin && onDeleteTag && (
407+ < IconButton
408+ edge = "end"
409+ aria-label = "delete"
410+ size = "small"
411+ onClick = { ( ) => handleDeleteTag ( tag ) }
412+ color = "error"
413+ >
414+ < Delete fontSize = "small" />
415+ </ IconButton >
416+ ) }
417+ </ ListItemSecondaryAction >
418+ </ ListItem >
419+ ) ) }
420+ </ List >
421+ ) : (
422+ < Typography variant = "body2" color = "text.secondary" sx = { { py : 2 } } >
423+ No tags in this group
424+ </ Typography >
425+ ) }
426+ </ Box >
427+ ) }
428+
402429 { isAdmin && editMode && onAddTag && (
403430 < Box sx = { { px : 3 , py : 2 , borderTop : '1px solid #eee' } } >
404431 < Box sx = { { display : 'flex' , gap : 1 } } >
@@ -407,7 +434,7 @@ export function TagPage({
407434 label = "New Tag Name"
408435 value = { newTagName }
409436 onChange = { ( e ) => setNewTagName ( e . target . value ) }
410- onKeyPress = { ( e ) => {
437+ onKeyDown = { ( e ) => {
411438 if ( e . key === 'Enter' ) {
412439 e . preventDefault ( ) ;
413440 handleAddNewTag ( ) ;
@@ -427,14 +454,11 @@ export function TagPage({
427454 </ Box >
428455 ) }
429456 </ DialogContent >
430- < DialogActions >
431- < Button onClick = { handleCloseDialog } > { isAdmin ? 'Cancel' : 'Close' } </ Button >
432- { isAdmin && (
433- < Button variant = "contained" onClick = { handleSave } >
434- Save
435- </ Button >
436- ) }
437- </ DialogActions >
457+ { editMode && (
458+ < DialogActions >
459+ < Button onClick = { handleCloseDialog } > Close</ Button >
460+ </ DialogActions >
461+ ) }
438462 </ Dialog >
439463
440464 { /* Tag Dialog */ }
0 commit comments