@@ -53,6 +53,22 @@ const tailwindColors = resolveConfig(tailwindConfig).theme.colors
5353
5454const coordsFractionDigits = 7
5555
56+ function UnwrittenChangesWarning ( { unwrittenChanges } ) {
57+ const firstUnwrittenTab = Object . entries ( unwrittenChanges ) . find (
58+ ( [ , changed ] ) => changed ,
59+ )
60+
61+ return (
62+ < >
63+ { firstUnwrittenTab && (
64+ < p className = "text-red-400 text-center" >
65+ You have unwritten { firstUnwrittenTab [ 0 ] } changes.
66+ </ p >
67+ ) }
68+ </ >
69+ )
70+ }
71+
5672export default function Missions ( ) {
5773 // Local Storage
5874 const [ connected ] = useSessionStorage ( {
@@ -68,6 +84,15 @@ export default function Missions() {
6884 // Need to keep a reference to the active tab to avoid stale closures
6985 const activeTabRef = useRef ( activeTab )
7086
87+ const [ unwrittenChanges , setUnwrittenChanges ] = useSessionStorage ( {
88+ key : "unwrittenChanges" ,
89+ defaultValue : {
90+ mission : false ,
91+ fence : false ,
92+ rally : false ,
93+ } ,
94+ } )
95+
7196 // Mission data
7297 const [ missionItems , setMissionItems ] = useSessionStorage ( {
7398 key : "missionItems" ,
@@ -126,10 +151,6 @@ export default function Missions() {
126151 [ ] ,
127152 )
128153
129- useEffect ( ( ) => {
130- setActiveTab ( "mission" ) // Default to mission tab on load
131- } , [ ] )
132-
133154 useEffect ( ( ) => {
134155 if ( ! connected ) {
135156 return
@@ -173,18 +194,21 @@ export default function Missions() {
173194 }
174195 updateHomePositionBasedOnWaypoints ( missionItemsWithIds )
175196 setMissionItems ( missionItemsWithIds )
197+ setUnwrittenChanges ( ( prev ) => ( { ...prev , mission : false } ) )
176198 } else if ( data . mission_type === "fence" ) {
177199 const fenceItemsWithIds = [ ]
178200 for ( let fence of data . items ) {
179201 fenceItemsWithIds . push ( addIdToItem ( fence ) )
180202 }
181203 setFenceItems ( fenceItemsWithIds )
204+ setUnwrittenChanges ( ( prev ) => ( { ...prev , fence : false } ) )
182205 } else if ( data . mission_type === "rally" ) {
183206 const rallyItemsWithIds = [ ]
184207 for ( let rallyItem of data . items ) {
185208 rallyItemsWithIds . push ( addIdToItem ( rallyItem ) )
186209 }
187210 setRallyItems ( rallyItemsWithIds )
211+ setUnwrittenChanges ( ( prev ) => ( { ...prev , rally : false } ) )
188212 }
189213
190214 showSuccessNotification ( `${ data . mission_type } read successfully` )
@@ -195,6 +219,10 @@ export default function Missions() {
195219
196220 if ( data . success ) {
197221 showSuccessNotification ( data . message )
222+ setUnwrittenChanges ( ( prev ) => ( {
223+ ...prev ,
224+ [ activeTabRef . current ] : false ,
225+ } ) )
198226 } else {
199227 showErrorNotification ( data . message )
200228 }
@@ -209,21 +237,23 @@ export default function Missions() {
209237 }
210238
211239 updateHomePositionBasedOnWaypoints ( missionItemsWithIds )
212-
213240 setMissionItems ( missionItemsWithIds )
241+ setUnwrittenChanges ( ( prev ) => ( { ...prev , mission : true } ) )
214242 } else if ( data . mission_type === "fence" ) {
215243 const fenceItemsWithIds = [ ]
216244 for ( let fence of data . items ) {
217245 fenceItemsWithIds . push ( addIdToItem ( fence ) )
218246 }
219247 setFenceItems ( fenceItemsWithIds )
248+ setUnwrittenChanges ( ( prev ) => ( { ...prev , fence : true } ) )
220249 } else if ( data . mission_type === "rally" ) {
221250 const rallyItemsWithIds = [ ]
222251 for ( let rallyItem of data . items ) {
223252 rallyItemsWithIds . push ( addIdToItem ( rallyItem ) )
224253 }
225254
226255 setRallyItems ( rallyItemsWithIds )
256+ setUnwrittenChanges ( ( prev ) => ( { ...prev , rally : true } ) )
227257 }
228258 showSuccessNotification ( data . message )
229259 } else {
@@ -350,6 +380,11 @@ export default function Missions() {
350380
351381 setRallyItems ( ( prevItems ) => [ ...prevItems , newMissionItem ] )
352382 }
383+
384+ setUnwrittenChanges ( ( prev ) => ( {
385+ ...prev ,
386+ [ activeTabRef . current ] : true ,
387+ } ) )
353388 }
354389
355390 function createHomePositionItem ( ) {
@@ -401,13 +436,42 @@ export default function Missions() {
401436 )
402437 }
403438
439+ function isEqualItem ( newItem , itemsList ) {
440+ return (
441+ JSON . stringify ( itemsList . find ( ( item ) => item . id === newItem . id ) ) ===
442+ JSON . stringify ( newItem )
443+ )
444+ }
445+
446+ // Check if the updated mission item is equal to the current mission item
447+ // if so, don't update
448+
404449 if ( activeTabRef . current === "mission" ) {
450+ if ( isEqualItem ( updatedMissionItem , missionItems ) ) {
451+ return
452+ }
453+
405454 setMissionItems ( ( prevItems ) => getUpdatedItems ( prevItems ) )
406455 } else if ( activeTabRef . current === "fence" ) {
456+ if ( isEqualItem ( updatedMissionItem , fenceItems ) ) {
457+ return
458+ }
459+
407460 setFenceItems ( ( prevItems ) => getUpdatedItems ( prevItems ) )
408461 } else if ( activeTabRef . current === "rally" ) {
462+ if ( isEqualItem ( updatedMissionItem , rallyItems ) ) {
463+ return
464+ }
465+
409466 setRallyItems ( ( prevItems ) => getUpdatedItems ( prevItems ) )
467+ } else {
468+ return
410469 }
470+
471+ setUnwrittenChanges ( ( prev ) => ( {
472+ ...prev ,
473+ [ activeTabRef . current ] : true ,
474+ } ) )
411475 }
412476
413477 function deleteMissionItem ( missionItemId ) {
@@ -427,6 +491,11 @@ export default function Missions() {
427491 } else if ( activeTabRef . current === "rally" ) {
428492 setRallyItems ( ( prevItems ) => getUpdatedItems ( prevItems ) )
429493 }
494+
495+ setUnwrittenChanges ( ( prev ) => ( {
496+ ...prev ,
497+ [ activeTabRef . current ] : true ,
498+ } ) )
430499 }
431500
432501 function updateMissionItemOrder ( missionItemId , indexIncrement ) {
@@ -464,8 +533,10 @@ export default function Missions() {
464533
465534 if ( activeTabRef . current === "mission" ) {
466535 setMissionItems ( ( prevItems ) => updateItemOrder ( prevItems ) )
536+ setUnwrittenChanges ( ( prev ) => ( { ...prev , mission : true } ) )
467537 } else if ( activeTabRef . current === "fence" ) {
468538 setFenceItems ( ( prevItems ) => updateItemOrder ( prevItems ) )
539+ setUnwrittenChanges ( ( prev ) => ( { ...prev , fence : true } ) )
469540 }
470541 }
471542
@@ -600,6 +671,8 @@ export default function Missions() {
600671 }
601672 setMissionItems ( ( prevItems ) => [ newHomeMissionItem , ...prevItems ] )
602673 }
674+
675+ setUnwrittenChanges ( ( prev ) => ( { ...prev , mission : true } ) )
603676 }
604677
605678 function clearMissionItems ( ) {
@@ -618,6 +691,11 @@ export default function Missions() {
618691 } else if ( activeTabRef . current === "rally" ) {
619692 setRallyItems ( [ ] )
620693 }
694+
695+ setUnwrittenChanges ( ( prev ) => ( {
696+ ...prev ,
697+ [ activeTabRef . current ] : true ,
698+ } ) )
621699 }
622700
623701 function addFencePolygon ( newFenceItems ) {
@@ -655,6 +733,7 @@ export default function Missions() {
655733 } )
656734
657735 setFenceItems ( ( prevItems ) => [ ...prevItems , ...newFenceMissionItems ] )
736+ setUnwrittenChanges ( ( prev ) => ( { ...prev , fence : true } ) )
658737 }
659738
660739 return (
@@ -716,6 +795,10 @@ export default function Missions() {
716795 >
717796 < div className = "flex flex-col gap-8 p-4" >
718797 < div className = "flex flex-col gap-4" >
798+ < UnwrittenChangesWarning
799+ unwrittenChanges = { unwrittenChanges }
800+ />
801+
719802 < Button
720803 onClick = { ( ) => {
721804 readMissionFromDrone ( )
0 commit comments