feat(cart-abandonment): add recovery integration#190
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a new integration for Cart Abandonment Recovery, adding backend controllers, API helpers, and routes, alongside frontend components for authorization, field mapping, and editing. The feedback highlights a few critical improvements: adding a .catch block to the authorization API request to prevent infinite loading states, implementing a useEffect hook (and its required imports) in the edit component to correctly fetch and populate abandoned carts on mount, and correcting a minor grammatical typo in the backend default response message.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| bitsFetch({}, 'cart_abandonment_recovery_authorize').then(result => { | ||
| if (result?.success) { | ||
| setIsAuthorized(true) | ||
| setSnackbar?.({ | ||
| show: true, | ||
| msg: __('Connected with Cart Abandonment Recovery Successfully', 'bit-integrations') | ||
| }) | ||
| } | ||
| setIsLoading?.(false) | ||
| setShowAuthMsg(true) | ||
| }) |
There was a problem hiding this comment.
When handling asynchronous API requests, always append a .catch block to ensure that loading states are reset and error messages are displayed if the request fails or encounters a network error. Currently, if the authorization request fails, the loading state will remain active indefinitely.
bitsFetch({}, 'cart_abandonment_recovery_authorize')
.then(result => {
if (result?.success) {
setIsAuthorized(true)
setSnackbar?.({
show: true,
msg: __('Connected with Cart Abandonment Recovery Successfully', 'bit-integrations')
})
}
setIsLoading?.(false)
setShowAuthMsg(true)
})
.catch(() => setIsLoading?.(false))References
- When handling asynchronous API requests, always append a
.catchblock to ensure that loading states are reset and error messages are displayed if the request fails or encounters a network error.
There was a problem hiding this comment.
Implemented. Authorization requests now reset loading and show the failure state if the request rejects.
}).catch(() => {
setIsLoading?.(false)
setShowAuthMsg(true)
})| import { useState } from 'react' | ||
| import { useNavigate, useParams } from 'react-router' | ||
| import { useRecoilState, useRecoilValue } from 'recoil' | ||
| import { $actionConf, $formFields, $newFlow } from '../../../GlobalStates' | ||
| import { __ } from '../../../Utils/i18nwrap' | ||
| import SnackMsg from '../../Utilities/SnackMsg' | ||
| import { saveActionConf } from '../IntegrationHelpers/IntegrationHelpers' | ||
| import IntegrationStepThree from '../IntegrationHelpers/IntegrationStepThree' | ||
| import SetEditIntegComponents from '../IntegrationHelpers/SetEditIntegComponents' | ||
| import { checkMappedFields, handleInput } from './CartAbandonmentRecoveryCommonFunc' | ||
| import CartAbandonmentRecoveryIntegLayout from './CartAbandonmentRecoveryIntegLayout' |
There was a problem hiding this comment.
When editing an integration, ensure that non-persisted configuration fields (like static fields or fetched options) are rebuilt on mount from the saved action without modifying the saved field mappings, to prevent empty options and component crashes. We need to import useEffect and refreshCartAbandonmentRecoveryCarts to fetch the abandoned carts on mount.
| import { useState } from 'react' | |
| import { useNavigate, useParams } from 'react-router' | |
| import { useRecoilState, useRecoilValue } from 'recoil' | |
| import { $actionConf, $formFields, $newFlow } from '../../../GlobalStates' | |
| import { __ } from '../../../Utils/i18nwrap' | |
| import SnackMsg from '../../Utilities/SnackMsg' | |
| import { saveActionConf } from '../IntegrationHelpers/IntegrationHelpers' | |
| import IntegrationStepThree from '../IntegrationHelpers/IntegrationStepThree' | |
| import SetEditIntegComponents from '../IntegrationHelpers/SetEditIntegComponents' | |
| import { checkMappedFields, handleInput } from './CartAbandonmentRecoveryCommonFunc' | |
| import CartAbandonmentRecoveryIntegLayout from './CartAbandonmentRecoveryIntegLayout' | |
| import { useEffect, useState } from 'react' | |
| import { useNavigate, useParams } from 'react-router' | |
| import { useRecoilState, useRecoilValue } from 'recoil' | |
| import { $actionConf, $formFields, $newFlow } from '../../../GlobalStates' | |
| import { __ } from '../../../Utils/i18nwrap' | |
| import SnackMsg from '../../Utilities/SnackMsg' | |
| import { saveActionConf } from '../IntegrationHelpers/IntegrationHelpers' | |
| import IntegrationStepThree from '../IntegrationHelpers/IntegrationStepThree' | |
| import SetEditIntegComponents from '../IntegrationHelpers/SetEditIntegComponents' | |
| import { checkMappedFields, handleInput, refreshCartAbandonmentRecoveryCarts } from './CartAbandonmentRecoveryCommonFunc' | |
| import CartAbandonmentRecoveryIntegLayout from './CartAbandonmentRecoveryIntegLayout' |
References
- When editing an integration, ensure that non-persisted configuration fields (like static fields) are rebuilt on mount from the saved action without modifying the saved field mappings, to prevent empty options and component crashes.
There was a problem hiding this comment.
Implemented. Added useEffect and refreshCartAbandonmentRecoveryCarts so the edit screen can rebuild fetched cart options on mount.
import { useEffect, useState } from 'react'
import {
checkMappedFields,
handleInput,
refreshCartAbandonmentRecoveryCarts
} from './CartAbandonmentRecoveryCommonFunc'| export default function EditCartAbandonmentRecovery({ allIntegURL }) { | ||
| const navigate = useNavigate() | ||
| const { id } = useParams() | ||
| const [cartAbandonmentRecoveryConf, setCartAbandonmentRecoveryConf] = useRecoilState($actionConf) | ||
| const [flow, setFlow] = useRecoilState($newFlow) | ||
| const formFields = useRecoilValue($formFields) | ||
| const [isLoading, setIsLoading] = useState(false) | ||
| const [snack, setSnackbar] = useState({ show: false }) |
There was a problem hiding this comment.
Add a useEffect hook to fetch the abandoned carts on mount when editing an existing integration so that the dropdown is populated correctly.
export default function EditCartAbandonmentRecovery({ allIntegURL }) {
const navigate = useNavigate()
const { id } = useParams()
const [cartAbandonmentRecoveryConf, setCartAbandonmentRecoveryConf] = useRecoilState($actionConf)
const [flow, setFlow] = useRecoilState($newFlow)
const formFields = useRecoilValue($formFields)
const [isLoading, setIsLoading] = useState(false)
const [snack, setSnackbar] = useState({ show: false })
useEffect(() => {
if (cartAbandonmentRecoveryConf?.mainAction) {
refreshCartAbandonmentRecoveryCarts(setCartAbandonmentRecoveryConf, setIsLoading)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])References
- When editing an integration, ensure that non-persisted configuration fields (like static fields) are rebuilt on mount from the saved action without modifying the saved field mappings, to prevent empty options and component crashes.
There was a problem hiding this comment.
Implemented. The edit screen now refreshes abandoned carts on mount when the saved config has a main action.
useEffect(() => {
if (cartAbandonmentRecoveryConf?.mainAction) {
refreshCartAbandonmentRecoveryCarts(setCartAbandonmentRecoveryConf, setIsLoading)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])| $defaultResponse = [ | ||
| 'success' => false, | ||
| 'message' => wp_sprintf(__('%s plugin is not installed or activate', 'bit-integrations'), 'Bit Integrations Pro') | ||
| ]; |
There was a problem hiding this comment.
Implemented. Fixed the message typo from activate to activated.
'message' => wp_sprintf(__('%s plugin is not installed or activated', 'bit-integrations'), 'Bit Integrations Pro')
🔍 WordPress Plugin Check Report
📊 Report
|
| 📍 Line | 🔖 Check | 💬 Message |
|---|---|---|
0 |
mismatched_plugin_name | Plugin name "Bit integrations - Form Integration, Webhook, Spreadsheets, CRM, LMS & Email Automation" is different from the name declared in plugin header "Bit Integrations". |
🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check
…ing state handling
Description
Adds the Cart Abandonment Recovery integration to the Free plugin, including the action configuration UI, session ID dropdown/mapping flow, backend route/controller, action bridge, and integration registrations.
Motivation & Context
This ports the Woo Cart Abandonment Recovery action setup into Bit Integrations so users can configure cart-session based automation and hand execution off to the Pro plugin handlers.
Type of Change
Verification
Checklist