@@ -1412,6 +1412,8 @@ export default function ProjectManagement({
14121412
14131413 // 🧠 NORMAL MERGE (REALTIME / OPTIMISTIC SAFE)
14141414 setTasks ( ( localTasks ) => {
1415+ // console.log("[ProjectManagement] merging tasks", { serverTasksCount: serverTasks.length, localTasksCount: localTasks.length });
1416+
14151417 // 1) Group local tasks by ID (real and tmp) and clientId (if available)
14161418 const localById = new Map ( localTasks . map ( ( t ) => [ nid ( t . id ) , t ] ) ) ;
14171419 const localByClientId = new Map ( ) ;
@@ -1480,6 +1482,10 @@ export default function ProjectManagement({
14801482 const localOnly = localTasks . filter ( ( lt ) => {
14811483 const id = nid ( lt . id ) ;
14821484 const cid = nid ( ( lt as any ) . clientId ) ;
1485+
1486+ // If creatingTask is true and this is a tmp task, definitely keep it!
1487+ if ( creatingTask && id . startsWith ( "tmp_" ) ) return true ;
1488+
14831489 return ! serverIds . has ( id ) && ( ! cid || ! serverClientIds . has ( cid ) ) ;
14841490 } ) ;
14851491
@@ -1489,22 +1495,60 @@ export default function ProjectManagement({
14891495 const mergedMap = new Map ( merged . map ( ( t ) => [ nid ( t . id ) , t ] ) ) ;
14901496 setSelectedTask ( ( cur ) => {
14911497 if ( ! cur ) return null ;
1492- const found = mergedMap . get ( nid ( cur . id ) ) ;
1498+ const curId = nid ( cur . id ) ;
1499+ const curCid = nid ( ( cur as any ) . clientId ) ;
1500+
1501+ const found = mergedMap . get ( curId ) ;
14931502 if ( found ) return found ;
14941503
1495- // keep optimistic task if it's currently selected
1496- if ( nid ( cur . id ) . startsWith ( "tmp_" ) ) return cur ;
1504+ // check by clientId as fallback (if cur has a clientId)
1505+ if ( curCid ) {
1506+ const foundByCid = Array . from ( mergedMap . values ( ) ) . find (
1507+ ( t ) => nid ( ( t as any ) . clientId ) === curCid || nid ( t . id ) === curCid ,
1508+ ) ;
1509+ if ( foundByCid ) return foundByCid ;
1510+ }
1511+
1512+ // If creatingTask is true, don't auto-close!
1513+ if ( creatingTask ) {
1514+ return cur ;
1515+ }
1516+
1517+ // keep optimistic task if it's currently selected and not yet in merged list
1518+ if ( curId . startsWith ( "tmp_" ) ) {
1519+ return cur ;
1520+ }
14971521
14981522 // also keep if it's in localTasks (prevents auto-close during creation)
1499- const inLocal = localTasks . find ( ( t ) => nid ( t . id ) === nid ( cur . id ) ) ;
1523+ const inLocal = localTasks . find (
1524+ ( t ) =>
1525+ nid ( t . id ) === curId ||
1526+ ( curCid && nid ( ( t as any ) . clientId ) === curCid ) ||
1527+ ( curCid && nid ( t . id ) === curCid ) ,
1528+ ) ;
15001529 if ( inLocal ) return inLocal ;
15011530
1531+ // If the current task is NOT in the merged map but was recently created (has clientId)
1532+ // we might still be waiting for the server to return it in the main task list.
1533+ if ( curCid && curCid . startsWith ( "tmp_" ) ) {
1534+ return cur ;
1535+ }
1536+
1537+ console . log (
1538+ "[ProjectManagement] auto-closing TaskModal: task not found in merged list" ,
1539+ {
1540+ curId,
1541+ curCid,
1542+ localTasksCount : localTasks . length ,
1543+ mergedCount : merged . length ,
1544+ } ,
1545+ ) ;
15021546 return null ;
15031547 } ) ;
15041548
15051549 return merged ;
15061550 } ) ;
1507- } , [ tasksQuery . data , activeProjectId , dateRangeKey ] ) ;
1551+ } , [ tasksQuery . data , activeProjectId , dateRangeKey , creatingTask ] ) ;
15081552
15091553 async function handleAddTask ( title : string ) {
15101554 if ( ! activeProjectId ) {
@@ -1514,11 +1558,13 @@ export default function ProjectManagement({
15141558 if ( creatingTask ) return ;
15151559 setCreatingTask ( true ) ;
15161560 playSound ( "/sounds/incoming.mp3" , isPlaySound ) ;
1561+
15171562 const optimistic : Task = {
15181563 id : `tmp_${ Math . random ( ) . toString ( 36 ) . slice ( 2 , 9 ) } ` ,
15191564 title,
15201565 status : "todo" as Task [ "status" ] ,
15211566 projectId : activeProjectId || null ,
1567+ workspaceId : activeWorkspaceId || null , // ensure workspaceId is included
15221568 comments : [ ] ,
15231569 priority : "low" as Task [ "priority" ] ,
15241570 taskAssignees : [ ] ,
@@ -1532,26 +1578,30 @@ export default function ProjectManagement({
15321578 setSelectedTask ( optimistic ) ;
15331579
15341580 try {
1535- const { id : _tmp , ...payload } = { ...optimistic , title } as any ;
1536- const created = await createTaskMutation . mutateAsync ( {
1537- ...payload ,
1538- clientId : optimistic . id ,
1539- } ) ;
1581+ const payload = { ...optimistic , title, clientId : optimistic . id } ;
1582+ delete ( payload as any ) . id ; // Remove tmp_ ID so server generates real one
1583+
1584+ console . log ( "[handleAddTask] mutation started with payload:" , payload ) ;
1585+ const created = await createTaskMutation . mutateAsync ( payload ) ;
1586+ console . log ( "[handleAddTask] mutation success:" , created ) ;
1587+
1588+ // Merge optimistic and created to ensure no data loss (e.g. projectId)
1589+ const mergedTask = { ...optimistic , ...created , clientId : optimistic . id } ;
15401590
15411591 setTasks ( ( s ) => {
15421592 const replaced = s . map ( ( t ) =>
1543- nid ( t . id ) === nid ( optimistic . id )
1544- ? { ...created , clientId : optimistic . id }
1545- : t ,
1593+ nid ( t . id ) === nid ( optimistic . id ) ? mergedTask : t ,
15461594 ) ;
15471595 const map = new Map < string , Task > ( ) ;
15481596 for ( const t of replaced ) map . set ( nid ( t . id ) , t ) ;
15491597 return Array . from ( map . values ( ) ) ;
15501598 } ) ;
15511599
15521600 setSelectedTask ( ( cur ) =>
1553- cur && nid ( cur . id ) === nid ( optimistic . id )
1554- ? { ...created , clientId : optimistic . id }
1601+ cur &&
1602+ ( nid ( cur . id ) === nid ( optimistic . id ) ||
1603+ nid ( ( cur as any ) . clientId ) === nid ( optimistic . id ) )
1604+ ? mergedTask
15551605 : cur ,
15561606 ) ;
15571607
0 commit comments