feat(modern-cart): add ModernCart integration#191
Conversation
…e modernCart image asset
There was a problem hiding this comment.
Code Review
This pull request introduces a new integration for Modern Cart, adding backend controllers, API helpers, and routes, alongside frontend components for authorization, configuration, and field mapping. The review feedback highlights two key improvements: first, adding a useEffect hook on mount in EditModernCart.jsx to rebuild non-persisted configuration fields and fetch dynamic data when editing an existing integration; second, appending a .catch block to the asynchronous bitsFetch request in ModernCartAuthorization.jsx to ensure that loading states are correctly reset in case of network or API failures.
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.
| 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 './ModernCartCommonFunc' | ||
| import ModernCartIntegLayout from './ModernCartIntegLayout' | ||
|
|
||
| export default function EditModernCart({ allIntegURL }) { | ||
| const navigate = useNavigate() | ||
| const { id, formID } = useParams() | ||
|
|
||
| const [modernCartConf, setModernCartConf] = 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.
When editing an integration, non-persisted configuration fields (such as static fields like modernCartFields) and dynamically fetched data (like products, variations, and cart items) must be rebuilt or fetched on mount. Currently, these are only fetched when the main action is changed manually, which leaves the dropdowns empty and hides the field mapping section when editing an existing integration. Adding a useEffect hook on mount resolves this issue.
import { create } from 'mutative'
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,
refreshModernCartCartItems,
refreshModernCartProducts,
refreshModernCartProductVariations
} from './ModernCartCommonFunc'
import ModernCartIntegLayout from './ModernCartIntegLayout'
import {
AddProductToCartFields,
RemoveProductFromCartFields,
UpdateCartQuantityFields
} from './staticData'
export default function EditModernCart({ allIntegURL }) {
const navigate = useNavigate()
const { id, formID } = useParams()
const [modernCartConf, setModernCartConf] = useRecoilState($actionConf)
const [flow, setFlow] = useRecoilState($newFlow)
const formFields = useRecoilValue($formFields)
const [isLoading, setIsLoading] = useState(false)
const [snack, setSnackbar] = useState({ show: false })
useEffect(() => {
let fields = []
if (modernCartConf.mainAction === 'add_product_to_cart') {
fields = AddProductToCartFields
refreshModernCartProducts(setModernCartConf, setIsLoading)
if (modernCartConf.productId) {
refreshModernCartProductVariations(modernCartConf.productId, setModernCartConf, setIsLoading)
}
} else if (modernCartConf.mainAction === 'update_cart_quantity') {
fields = UpdateCartQuantityFields
refreshModernCartCartItems(setModernCartConf, setIsLoading)
} else if (modernCartConf.mainAction === 'remove_product_from_cart') {
fields = RemoveProductFromCartFields
}
setModernCartConf(prevConf =>
create(prevConf, draftConf => {
draftConf.modernCartFields = fields
})
)
}, [])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 locally. The edit screen now rebuilds modernCartFields on mount and refetches the action-specific dropdown data without touching the saved field map:
useEffect(() => {
let fields = []
if (modernCartConf?.mainAction === 'add_product_to_cart') {
fields = AddProductToCartFields
refreshModernCartProducts(setModernCartConf, setIsLoading)
if (modernCartConf?.productId) {
refreshModernCartProductVariations(modernCartConf.productId, setModernCartConf, setIsLoading)
}
} else if (modernCartConf?.mainAction === 'update_cart_quantity') {
fields = UpdateCartQuantityFields
refreshModernCartCartItems(setModernCartConf, setIsLoading)
} else if (modernCartConf?.mainAction === 'remove_product_from_cart') {
fields = RemoveProductFromCartFields
}
}, [])| bitsFetch({}, 'modern_cart_authorize').then(result => { | ||
| if (result?.success) { | ||
| setIsAuthorized(true) | ||
| setSnackbar({ | ||
| show: true, | ||
| msg: __('Connected with Modern Cart 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.
| bitsFetch({}, 'modern_cart_authorize').then(result => { | |
| if (result?.success) { | |
| setIsAuthorized(true) | |
| setSnackbar({ | |
| show: true, | |
| msg: __('Connected with Modern Cart Successfully', 'bit-integrations') | |
| }) | |
| } | |
| setIsLoading(false) | |
| setShowAuthMsg(true) | |
| }) | |
| bitsFetch({}, 'modern_cart_authorize') | |
| .then(result => { | |
| if (result?.success) { | |
| setIsAuthorized(true) | |
| setSnackbar({ | |
| show: true, | |
| msg: __('Connected with Modern Cart Successfully', 'bit-integrations') | |
| }) | |
| } | |
| setIsLoading(false) | |
| setShowAuthMsg(true) | |
| }) | |
| .catch(() => { | |
| setIsLoading(false) | |
| setShowAuthMsg(true) | |
| }) |
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 locally. Added a .catch() path so failed authorization requests reset loading state, show the auth result block, and display a retry message:
.catch(() => {
setSnackbar({
show: true,
msg: __('Modern Cart authorization failed. Please try again', 'bit-integrations')
})
setIsLoading(false)
setShowAuthMsg(true)
})
✅ WordPress Plugin Check Report
📊 ReportAll checks passed! No errors or warnings found. 🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check |
…dling and success messaging
Description
Adds the ModernCart integration to Bit Integrations Free with action setup UI, backend fetch routes, field mapping, and integration registration. Also hardens cart field configuration for variable products and cart item selection.
Motivation & Context
ModernCart needs Free-side configuration and fetch support so Pro can execute cart actions safely. This also fixes review issues around required variation selection, supported product filtering, and stale cart item metadata.
Related Links: (if applicable)
Type of Change
Key Changes
Integrations
Validation
Checklist
Changelog