@@ -37,7 +37,7 @@ import { useView, defaultLayouts } from './views';
3737
3838const EMPTY_ARRAY = [ ] ;
3939const MOBILE_BREAKPOINT = 780 ;
40- const getItemId = item => item . id . toString ( ) ;
40+ const getItemId = item => item ? .id ? .toString ( ) ?? '' ;
4141
4242const formatFieldName = fieldName => {
4343 const match = fieldName . match ( / ^ ( \d + _ ) ? ( .* ) / i ) ;
@@ -207,16 +207,33 @@ export default function InboxView() {
207207 // set the sidePanelItem when we have data and selection.
208208 // We don't need to do this in `mobile`, because we don't render the side panel.
209209 if ( ! isMobile && ! ! data && ! ! selection . length ) {
210- const firstValidSelection = selection . find ( id =>
211- data . some ( record => getItemId ( record ) === id )
212- ) ;
213- const recordToShow = data ?. find ( record => getItemId ( record ) === firstValidSelection ) ;
210+ // Find the last (most recently selected) valid selection instead of the first
211+ const lastValidSelection = selection
212+ . slice ( )
213+ . reverse ( )
214+ . find ( id => data . some ( record => getItemId ( record ) === id ) ) ;
215+ const recordToShow = data ?. find ( record => getItemId ( record ) === lastValidSelection ) ;
214216 if ( ! sidePanelItem && recordToShow ) {
215217 setSidePanelItem ( recordToShow ) ;
216218 } else if ( ! ! sidePanelItem && ! recordToShow ) {
217219 // This case handles the case where we were having a side panel item
218220 // visible but the data have changed and the item is not there anymore.
219221 setSidePanelItem ( ) ;
222+ } else if (
223+ ! ! sidePanelItem &&
224+ ! ! recordToShow &&
225+ getItemId ( sidePanelItem ) === getItemId ( recordToShow ) &&
226+ sidePanelItem !== recordToShow
227+ ) {
228+ // Update side panel item if the data has been refreshed for the SAME item (e.g., after an action)
229+ // This ensures the side panel shows the latest version of the same entity
230+ setSidePanelItem ( recordToShow ) ;
231+ } else if (
232+ ! ! recordToShow &&
233+ ( ! sidePanelItem || getItemId ( sidePanelItem ) !== getItemId ( recordToShow ) )
234+ ) {
235+ // Set side panel item when selecting a different item
236+ setSidePanelItem ( recordToShow ) ;
220237 }
221238 }
222239 const paginationInfo = useMemo (
@@ -337,19 +354,30 @@ export default function InboxView() {
337354 setSidePanelItem = { setSidePanelItem }
338355 isLoadingData = { isLoadingData }
339356 isMobile = { isMobile }
357+ data = { data }
358+ onChangeSelection = { onChangeSelection }
359+ selection = { selection }
340360 />
341361 </ HStack >
342362 ) ;
343363}
344364
345- const SingleResponse = ( { sidePanelItem, setSidePanelItem, isLoadingData, isMobile } ) => {
365+ const SingleResponse = ( {
366+ sidePanelItem,
367+ setSidePanelItem,
368+ isLoadingData,
369+ isMobile,
370+ data,
371+ onChangeSelection,
372+ selection,
373+ } ) => {
346374 const [ isChildModalOpen , setIsChildModalOpen ] = useState ( false ) ;
347375
348376 const onRequestClose = useCallback ( ( ) => {
349377 if ( ! isChildModalOpen ) {
350- setSidePanelItem ( ) ;
378+ onChangeSelection ( [ ] ) ;
351379 }
352- } , [ setSidePanelItem , isChildModalOpen ] ) ;
380+ } , [ onChangeSelection , isChildModalOpen ] ) ;
353381
354382 const handleModalStateChange = useCallback (
355383 isOpen => {
@@ -358,22 +386,68 @@ const SingleResponse = ( { sidePanelItem, setSidePanelItem, isLoadingData, isMob
358386 [ setIsChildModalOpen ]
359387 ) ;
360388
389+ const handleActionComplete = useCallback (
390+ actionedItemId => {
391+ // Remove only the actioned item from selection, keep the rest
392+ if ( actionedItemId && selection ) {
393+ const newSelection = selection . filter ( id => id !== actionedItemId ) ;
394+ onChangeSelection ( newSelection ) ;
395+ }
396+ } ,
397+ [ onChangeSelection , selection ]
398+ ) ;
399+
400+ // Navigation logic
401+ const currentIndex =
402+ sidePanelItem && data
403+ ? data . findIndex ( item => getItemId ( item ) === getItemId ( sidePanelItem ) )
404+ : - 1 ;
405+ const hasNext = currentIndex >= 0 && currentIndex < ( data ?. length ?? 0 ) - 1 ;
406+ const hasPrevious = currentIndex > 0 ;
407+
408+ const handleNext = useCallback ( ( ) => {
409+ if ( hasNext && data && currentIndex >= 0 ) {
410+ const nextItem = data [ currentIndex + 1 ] ;
411+ if ( nextItem ) {
412+ setSidePanelItem ( nextItem ) ;
413+ onChangeSelection ( [ getItemId ( nextItem ) ] ) ;
414+ }
415+ }
416+ } , [ hasNext , data , currentIndex , setSidePanelItem , onChangeSelection ] ) ;
417+
418+ const handlePrevious = useCallback ( ( ) => {
419+ if ( hasPrevious && data && currentIndex >= 0 ) {
420+ const prevItem = data [ currentIndex - 1 ] ;
421+ if ( prevItem ) {
422+ setSidePanelItem ( prevItem ) ;
423+ onChangeSelection ( [ getItemId ( prevItem ) ] ) ;
424+ }
425+ }
426+ } , [ hasPrevious , data , currentIndex , setSidePanelItem , onChangeSelection ] ) ;
427+
361428 if ( ! sidePanelItem ) {
362429 return null ;
363430 }
364431 const contents = (
365432 < InboxResponse
366433 response = { sidePanelItem }
367434 isLoading = { isLoadingData }
435+ isMobile = { isMobile }
368436 onModalStateChange = { handleModalStateChange }
437+ onClose = { onRequestClose }
438+ onNext = { handleNext }
439+ onPrevious = { handlePrevious }
440+ hasNext = { hasNext }
441+ hasPrevious = { hasPrevious }
442+ onActionComplete = { handleActionComplete }
369443 />
370444 ) ;
371445 if ( ! isMobile ) {
372446 return < div className = "jp-forms__inbox__dataviews-response" > { contents } </ div > ;
373447 }
374448 return (
375449 < Modal
376- title = { __ ( 'View response ' , 'jetpack-forms' ) }
450+ title = { __ ( 'Response ' , 'jetpack-forms' ) }
377451 size = "medium"
378452 onRequestClose = { onRequestClose }
379453 >
0 commit comments