@@ -22,7 +22,6 @@ import {
2222} from "../../../services/Task/BoundedTask" ;
2323import {
2424 receiveTasks ,
25- simulatedEntities ,
2625 subscribeToAllTasks ,
2726 subscribeToChallengeTaskMessages ,
2827 unsubscribeFromAllTasks ,
@@ -46,6 +45,7 @@ export const WithChallengeTaskClusters = function (
4645) {
4746 return class extends Component {
4847 _isMounted = false ;
48+ componentHandle = `challengeTaskClusters_${ Math . random ( ) . toString ( 36 ) . substring ( 2 , 15 ) } ` ;
4949
5050 state = {
5151 loading : false ,
@@ -236,9 +236,7 @@ export const WithChallengeTaskClusters = function (
236236
237237 const { dispatch, challengeId } = this . props ;
238238 if ( challengeId ) {
239- // Subscribe to challenge-specific task updates
240239 subscribeToChallengeTaskMessages ( dispatch , challengeId ) ;
241- // Also subscribe to all tasks to catch updates with our custom handler
242240 subscribeToAllTasks ( this . handleChallengeTaskUpdate , `${ this . componentHandle } _challenge` ) ;
243241 } else {
244242 subscribeToAllTasks ( this . handleGlobalTaskUpdate , this . componentHandle ) ;
@@ -247,83 +245,130 @@ export const WithChallengeTaskClusters = function (
247245
248246 handleGlobalTaskUpdate = ( messageObject ) => {
249247 const task = messageObject ?. data ?. task ;
248+ const tasks = messageObject ?. data ?. tasks ;
250249 const messageType = messageObject ?. messageType ;
251250
252251 if ( messageType === "task-claimed" && messageObject ?. data ?. byUser ?. userId ) {
253252 const updatedTask = {
254253 ...task ,
255254 lockedBy : messageObject . data . byUser . userId ,
256- lockedAt : new Date ( ) . toISOString ( ) ,
257255 } ;
258256 if ( this . isTaskInCurrentView ( updatedTask ) ) {
259257 this . updateTaskInClusters ( updatedTask ) ;
260258 }
259+ } else if ( messageType === "tasks-claimed" && messageObject ?. data ?. byUser ?. userId && tasks ) {
260+ const updatedTasks = tasks . map ( ( task ) => ( {
261+ ...task ,
262+ lockedBy : messageObject . data . byUser . userId ,
263+ } ) ) ;
264+
265+ const tasksInView = updatedTasks . filter ( ( task ) => this . isTaskInCurrentView ( task ) ) ;
266+ if ( tasksInView . length > 0 ) {
267+ this . updateTaskInClusters ( tasksInView ) ;
268+ }
261269 } else if ( messageType === "task-released" ) {
262270 const updatedTask = {
263271 ...task ,
264272 lockedBy : null ,
265- lockedAt : null ,
266273 } ;
267274 if ( this . isTaskInCurrentView ( updatedTask ) ) {
268275 this . updateTaskInClusters ( updatedTask ) ;
269276 }
277+ } else if ( messageType === "tasks-released" && tasks ) {
278+ const updatedTasks = tasks . map ( ( task ) => ( {
279+ ...task ,
280+ lockedBy : null ,
281+ } ) ) ;
282+
283+ const tasksInView = updatedTasks . filter ( ( task ) => this . isTaskInCurrentView ( task ) ) ;
284+ if ( tasksInView . length > 0 ) {
285+ this . updateTaskInClusters ( tasksInView ) ;
286+ }
270287 } else if ( task && this . isTaskInCurrentView ( task ) ) {
271288 this . updateTaskInClusters ( task ) ;
289+ } else if ( tasks ) {
290+ const tasksInView = tasks . filter ( ( task ) => this . isTaskInCurrentView ( task ) ) ;
291+ if ( tasksInView . length > 0 ) {
292+ this . updateTaskInClusters ( tasksInView ) ;
293+ }
272294 }
273295 } ;
274296
275297 handleChallengeTaskUpdate = async ( messageObject ) => {
298+ const task = messageObject ?. data ?. task ;
276299 const tasks = messageObject ?. data ?. tasks ;
277300 const messageType = messageObject ?. messageType ;
278301
279- if ( ! tasks ) return ;
302+ // Handle both single task and multiple task messages
303+ const tasksToProcess = tasks || ( task ? [ task ] : [ ] ) ;
280304
281- if ( messageType === "tasks-claimed" && messageObject ?. data ?. byUser ?. userId ) {
282- const updatedTasks = tasks . map ( ( task ) => ( {
305+ if ( tasksToProcess . length === 0 ) return ;
306+
307+ if ( messageType === "task-claimed" && messageObject ?. data ?. byUser ?. userId ) {
308+ const updatedTasks = tasksToProcess . map ( ( task ) => ( {
283309 ...task ,
284310 lockedBy : messageObject . data . byUser . userId ,
285- lockedAt : new Date ( ) . toISOString ( ) ,
311+ } ) ) ;
312+ this . updateTaskInClusters ( updatedTasks ) ;
313+ } else if ( messageType === "tasks-claimed" && messageObject ?. data ?. byUser ?. userId ) {
314+ const updatedTasks = tasksToProcess . map ( ( task ) => ( {
315+ ...task ,
316+ lockedBy : messageObject . data . byUser . userId ,
317+ } ) ) ;
318+ this . updateTaskInClusters ( updatedTasks ) ;
319+ } else if ( messageType === "task-released" ) {
320+ const updatedTasks = tasksToProcess . map ( ( task ) => ( {
321+ ...task ,
322+ lockedBy : null ,
286323 } ) ) ;
287324 this . updateTaskInClusters ( updatedTasks ) ;
288325 } else if ( messageType === "tasks-released" ) {
289- const updatedTasks = tasks . map ( ( task ) => ( {
326+ const updatedTasks = tasksToProcess . map ( ( task ) => ( {
290327 ...task ,
291328 lockedBy : null ,
292- lockedAt : null ,
293329 } ) ) ;
294330 this . updateTaskInClusters ( updatedTasks ) ;
295331 } else {
296- this . updateTaskInClusters ( tasks ) ;
332+ this . updateTaskInClusters ( tasksToProcess ) ;
297333 }
298334 } ;
299335
300336 updateTaskInClusters = async ( updatedTasks ) => {
301337 if ( ! Array . isArray ( updatedTasks ) ) {
302338 updatedTasks = [ updatedTasks ] ;
303339 }
340+ updatedTasks = updatedTasks . filter ( ( task ) => task ?. id ) ;
304341
305- updatedTasks . forEach ( ( updatedTask ) => {
306- if ( ! updatedTask ?. id ) {
307- return ;
308- }
309- const { dispatch } = this . props ;
310- if ( dispatch ) {
311- dispatch ( receiveTasks ( simulatedEntities ( updatedTask ) ) ) ;
312- }
342+ if ( updatedTasks . length === 0 ) {
343+ return ;
344+ }
313345
314- this . setState ( ( prevState ) => {
315- const clusters = Array . isArray ( prevState . clusters )
316- ? [ ...prevState . clusters ]
317- : prevState . clusters ;
346+ const { dispatch } = this . props ;
347+ if ( dispatch && updatedTasks . length > 0 ) {
348+ const tasksById = { } ;
349+ updatedTasks . forEach ( ( task ) => {
350+ tasksById [ task . id ] = task ;
351+ } ) ;
318352
319- if ( Array . isArray ( clusters ) ) {
320- const taskIndex = clusters . findIndex (
321- ( cluster ) => cluster . id === updatedTask . id || cluster . taskId === updatedTask . id ,
322- ) ;
353+ dispatch ( receiveTasks ( { tasks : tasksById } ) ) ;
354+ }
355+
356+ this . setState ( ( prevState ) => {
357+ const clusters = Array . isArray ( prevState . clusters )
358+ ? [ ...prevState . clusters ]
359+ : prevState . clusters ;
360+
361+ if ( Array . isArray ( clusters ) ) {
362+ const taskMap = new Map ( updatedTasks . map ( ( task ) => [ task . id , task ] ) ) ;
323363
324- if ( taskIndex !== - 1 ) {
325- clusters [ taskIndex ] = {
326- ...clusters [ taskIndex ] ,
364+ for ( let i = 0 ; i < clusters . length ; i ++ ) {
365+ const cluster = clusters [ i ] ;
366+ const clusterId = cluster . id || cluster . taskId ;
367+ const updatedTask = taskMap . get ( clusterId ) ;
368+
369+ if ( updatedTask ) {
370+ clusters [ i ] = {
371+ ...cluster ,
327372 status : updatedTask . status ,
328373 priority : updatedTask . priority ,
329374 reviewStatus : updatedTask . reviewStatus ,
@@ -332,27 +377,30 @@ export const WithChallengeTaskClusters = function (
332377 ...updatedTask ,
333378 } ;
334379 }
335- } else if ( typeof clusters === "object" ) {
336- let found = false ;
337- Object . keys ( clusters ) . forEach ( ( key ) => {
338- const cluster = clusters [ key ] ;
339- if ( cluster . id === updatedTask . id || cluster . taskId === updatedTask . id ) {
340- found = true ;
341- clusters [ key ] = {
342- ...cluster ,
343- status : updatedTask . status ,
344- priority : updatedTask . priority ,
345- reviewStatus : updatedTask . reviewStatus ,
346- lockedBy : updatedTask . lockedBy ,
347- lockedAt : updatedTask . lockedAt ,
348- ...updatedTask ,
349- } ;
350- }
351- } ) ;
352380 }
381+ } else if ( typeof clusters === "object" ) {
382+ const taskMap = new Map ( updatedTasks . map ( ( task ) => [ task . id , task ] ) ) ;
353383
354- return { clusters } ;
355- } ) ;
384+ Object . keys ( clusters ) . forEach ( ( key ) => {
385+ const cluster = clusters [ key ] ;
386+ const clusterId = cluster . id || cluster . taskId ;
387+ const updatedTask = taskMap . get ( clusterId ) ;
388+
389+ if ( updatedTask ) {
390+ clusters [ key ] = {
391+ ...cluster ,
392+ status : updatedTask . status ,
393+ priority : updatedTask . priority ,
394+ reviewStatus : updatedTask . reviewStatus ,
395+ lockedBy : updatedTask . lockedBy ,
396+ lockedAt : updatedTask . lockedAt ,
397+ ...updatedTask ,
398+ } ;
399+ }
400+ } ) ;
401+ }
402+
403+ return { clusters } ;
356404 } ) ;
357405 } ;
358406
@@ -364,7 +412,6 @@ export const WithChallengeTaskClusters = function (
364412 const bounds = this . props . criteria . boundingBox ;
365413 const [ lng , lat ] = task . location . coordinates ;
366414
367- // Parse bounds string (format: "west,south,east,north")
368415 const boundsArray = bounds . split ( "," ) . map ( Number ) ;
369416 if ( boundsArray . length !== 4 ) return false ;
370417
@@ -386,8 +433,8 @@ export const WithChallengeTaskClusters = function (
386433 }
387434
388435 debouncedFetchClusters = _debounce ( ( showAsClusters ) => {
389- if ( this . _isMounted ) this . fetchUpdatedClusters ( showAsClusters ) , 800 ;
390- } ) ;
436+ if ( this . _isMounted ) this . fetchUpdatedClusters ( showAsClusters ) ;
437+ } , 800 ) ;
391438
392439 componentDidUpdate ( prevProps ) {
393440 // Check if search query has changed
0 commit comments