@@ -14,6 +14,13 @@ function Teach() {
1414 const [ loading , setLoading ] = useState ( false ) ;
1515 const [ error , setError ] = useState < string | null > ( null ) ;
1616 const [ showAddDialog , setShowAddDialog ] = useState ( false ) ;
17+ const [ showConflictDialog , setShowConflictDialog ] = useState ( false ) ;
18+ const [ conflictData , setConflictData ] = useState < {
19+ storageId : string ;
20+ roadmapData : any ;
21+ jsonId ?: string ;
22+ existingMap : TeacherMapEntry ;
23+ } | null > ( null ) ;
1724
1825 useEffect ( ( ) => {
1926 db . getAllTeacherMaps ( ) . then ( setAllMaps ) ;
@@ -83,6 +90,16 @@ function Teach() {
8390 const roadmapData = await response . json ( ) ;
8491 const storageId = roadmapData . settings ?. id || jsonId ;
8592
93+ // Check if map already exists
94+ const existingMap = await db . getTeacherMap ( storageId ) ;
95+ if ( existingMap ) {
96+ // Show conflict dialog
97+ setConflictData ( { storageId, roadmapData, jsonId, existingMap } ) ;
98+ setShowConflictDialog ( true ) ;
99+ setLoading ( false ) ;
100+ return ;
101+ }
102+
86103 await db . addTeacherMap ( storageId , roadmapData , jsonId ) ;
87104 const maps = await db . getAllTeacherMaps ( ) ;
88105 setAllMaps ( maps ) ;
@@ -114,6 +131,15 @@ function Teach() {
114131 const uploadId = `upload-${ Date . now ( ) } ` ;
115132 const storageId = json . settings ?. id || uploadId ;
116133
134+ // Check if map already exists
135+ const existingMap = await db . getTeacherMap ( storageId ) ;
136+ if ( existingMap ) {
137+ // Show conflict dialog
138+ setConflictData ( { storageId, roadmapData : json , existingMap } ) ;
139+ setShowConflictDialog ( true ) ;
140+ return ;
141+ }
142+
117143 await db . addTeacherMap ( storageId , json , undefined ) ;
118144 const maps = await db . getAllTeacherMaps ( ) ;
119145 setAllMaps ( maps ) ;
@@ -133,6 +159,37 @@ function Teach() {
133159 event . target . value = '' ;
134160 } ;
135161
162+ const handleConflictOverwrite = async ( ) => {
163+ if ( ! conflictData ) return ;
164+
165+ await db . addTeacherMap ( conflictData . storageId , conflictData . roadmapData , conflictData . jsonId ) ;
166+ const maps = await db . getAllTeacherMaps ( ) ;
167+ setAllMaps ( maps ) ;
168+ setNewMapUrl ( '' ) ;
169+ setShowAddDialog ( false ) ;
170+ setShowConflictDialog ( false ) ;
171+ setConflictData ( null ) ;
172+ } ;
173+
174+ const handleConflictNewId = async ( ) => {
175+ if ( ! conflictData ) return ;
176+
177+ // Generate a new unique ID
178+ const newId = `${ conflictData . storageId } -${ Date . now ( ) } ` ;
179+ await db . addTeacherMap ( newId , conflictData . roadmapData , conflictData . jsonId ) ;
180+ const maps = await db . getAllTeacherMaps ( ) ;
181+ setAllMaps ( maps ) ;
182+ setNewMapUrl ( '' ) ;
183+ setShowAddDialog ( false ) ;
184+ setShowConflictDialog ( false ) ;
185+ setConflictData ( null ) ;
186+ } ;
187+
188+ const handleConflictCancel = ( ) => {
189+ setShowConflictDialog ( false ) ;
190+ setConflictData ( null ) ;
191+ } ;
192+
136193 return (
137194 < div className = "teach-container" >
138195 < Header >
@@ -195,6 +252,60 @@ function Teach() {
195252 </ div >
196253 ) }
197254
255+ { showConflictDialog && conflictData && (
256+ < div className = "dialog-overlay" onClick = { handleConflictCancel } >
257+ < div className = "dialog-content conflict-dialog" onClick = { ( e ) => e . stopPropagation ( ) } >
258+ < div className = "dialog-header" >
259+ < h2 > ⚠️ Map Already Exists</ h2 >
260+ < button
261+ className = "dialog-close"
262+ onClick = { handleConflictCancel }
263+ aria-label = "Close dialog"
264+ >
265+ ×
266+ </ button >
267+ </ div >
268+ < div className = "dialog-body" >
269+ < p >
270+ A learning map with ID < strong > { conflictData . storageId } </ strong > already exists in your collection.
271+ </ p >
272+ < div className = "conflict-info" >
273+ < div className = "conflict-map-info" >
274+ < h4 > Existing Map:</ h4 >
275+ < p > < strong > { conflictData . existingMap . roadmapData . settings ?. title || 'Untitled' } </ strong > </ p >
276+ < p className = "text-small" > Last modified: { new Date ( conflictData . existingMap . lastModified ) . toLocaleString ( ) } </ p >
277+ </ div >
278+ < div className = "conflict-map-info" >
279+ < h4 > New Map:</ h4 >
280+ < p > < strong > { conflictData . roadmapData . settings ?. title || 'Untitled' } </ strong > </ p >
281+ </ div >
282+ </ div >
283+ < p > What would you like to do?</ p >
284+ < div className = "conflict-actions" >
285+ < button
286+ onClick = { handleConflictOverwrite }
287+ className = "conflict-button conflict-button-danger"
288+ >
289+ Overwrite Existing
290+ </ button >
291+ < button
292+ onClick = { handleConflictNewId }
293+ className = "conflict-button conflict-button-primary"
294+ >
295+ Keep Both (New ID)
296+ </ button >
297+ < button
298+ onClick = { handleConflictCancel }
299+ className = "conflict-button conflict-button-secondary"
300+ >
301+ Cancel
302+ </ button >
303+ </ div >
304+ </ div >
305+ </ div >
306+ </ div >
307+ ) }
308+
198309 < div className = "teach-content" >
199310 < div className = "teach-header" >
200311 < h2 > My Created Maps</ h2 >
0 commit comments