@@ -42,6 +42,8 @@ export default function Notes() {
4242 const [ previewImage , setPreviewImage ] = useState ( null ) ;
4343 const [ searchTerm , setSearchTerm ] = useState ( '' ) ;
4444 const [ selectedTag , setSelectedTag ] = useState ( 'all' ) ;
45+ const [ saveStatus , setSaveStatus ] = useState ( 'idle' ) ; // 'idle', 'saving', 'saved', 'error'
46+ const [ isAutoSaving , setIsAutoSaving ] = useState ( false ) ;
4547
4648 useEffect ( ( ) => {
4749 if ( isAuthenticated && ! loading ) {
@@ -103,7 +105,9 @@ export default function Notes() {
103105 } ;
104106
105107 const handleClick = async ( ) => {
108+ setIsAutoSaving ( false ) ;
106109 try {
110+ setSaveStatus ( 'saving' ) ;
107111 let uploadedUrls = [ ] ;
108112 if ( newImages . length > 0 ) {
109113 uploadedUrls = await uploadImages ( newImages ) ;
@@ -118,6 +122,7 @@ export default function Notes() {
118122 note . etag ,
119123 finalImages
120124 ) ;
125+ setSaveStatus ( 'saved' ) ;
121126 setIsEditModalOpen ( false ) ;
122127 setExistingImages ( [ ] ) ;
123128 setNewImages ( [ ] ) ;
@@ -127,10 +132,38 @@ export default function Notes() {
127132 toast . success ( "Note updated successfully! 🎉" ) ;
128133 } catch ( error ) {
129134 console . error ( error ) ;
135+ setSaveStatus ( 'error' ) ;
130136 toast . error ( "Failed to update note" ) ;
131137 }
132138 } ;
133139
140+ // Autosave logic for editing
141+ useEffect ( ( ) => {
142+ if ( ! isEditModalOpen || ! note . id || isAutoSaving ) return ;
143+
144+ // Skip saving if content is too short (min length 5)
145+ if ( note . etitle . length < 5 || note . edescription . length < 5 || note . etag . length < 2 ) return ;
146+
147+ const timer = setTimeout ( async ( ) => {
148+ try {
149+ setSaveStatus ( 'saving' ) ;
150+ await editNote (
151+ note . id ,
152+ note . etitle ,
153+ note . edescription ,
154+ note . etag ,
155+ existingImages // Just save current images, new ones handled by manual save or upload-on-select
156+ ) ;
157+ setSaveStatus ( 'saved' ) ;
158+ } catch ( err ) {
159+ console . error ( "Autosave failed" , err ) ;
160+ setSaveStatus ( 'error' ) ;
161+ }
162+ } , 1000 ) ; // 1s debounce
163+
164+ return ( ) => clearTimeout ( timer ) ;
165+ } , [ note . etitle , note . edescription , note . etag , isEditModalOpen , note . id , editNote , existingImages ] ) ;
166+
134167 // Add new images
135168 const handleNewImageChange = ( e ) => {
136169 const files = Array . from ( e . target . files ) ;
@@ -195,7 +228,37 @@ export default function Notes() {
195228 < h2 className = "text-2xl font-bold text-white" >
196229 Edit Note
197230 </ h2 >
198- < p className = "text-gray-400 text-sm mt-1" > Update your note details</ p >
231+ < div className = "flex items-center mt-1" >
232+ < p className = "text-gray-400 text-sm" > Update your note details</ p >
233+ < span className = "mx-2 text-gray-600" > •</ span >
234+ < div className = "flex items-center text-xs" >
235+ { saveStatus === 'saving' && (
236+ < span className = "text-blue-400 flex items-center" >
237+ < svg className = "animate-spin h-3 w-3 mr-1" viewBox = "0 0 24 24" >
238+ < circle className = "opacity-25" cx = "12" cy = "12" r = "10" stroke = "currentColor" strokeWidth = "4" > </ circle >
239+ < path className = "opacity-75" fill = "currentColor" d = "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" > </ path >
240+ </ svg >
241+ Saving...
242+ </ span >
243+ ) }
244+ { saveStatus === 'saved' && (
245+ < span className = "text-green-400 flex items-center" >
246+ < svg className = "h-3 w-3 mr-1" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
247+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M5 13l4 4L19 7" />
248+ </ svg >
249+ All changes saved
250+ </ span >
251+ ) }
252+ { saveStatus === 'error' && (
253+ < span className = "text-red-400 flex items-center" >
254+ < svg className = "h-3 w-3 mr-1" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
255+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
256+ </ svg >
257+ Save failed
258+ </ span >
259+ ) }
260+ </ div >
261+ </ div >
199262 </ div >
200263 < button
201264 onClick = { ( ) => setIsEditModalOpen ( false ) }
@@ -585,4 +648,4 @@ export default function Notes() {
585648 </ div >
586649 </ >
587650 )
588- }
651+ }
0 commit comments