Skip to content

feat(modern-cart): add ModernCart integration#191

Open
RishadAlam wants to merge 7 commits into
mainfrom
feat/modern-cart
Open

feat(modern-cart): add ModernCart integration#191
RishadAlam wants to merge 7 commits into
mainfrom
feat/modern-cart

Conversation

@RishadAlam

Copy link
Copy Markdown
Member

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

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Improvement
  • Code refactor

Key Changes

Integrations

  • Added ModernCart action integration registration, UI screens, field mapper, and icon asset.
  • Added Free backend routes for authorization, products, variations, and cart item refreshes.

Validation

  • Fixed variable product setup so variation is required when needed.
  • Improved product and cart item dropdown data to avoid invalid mappings.

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Tests added/updated
  • Documentation updated if needed
  • README updated if needed

Changelog

  • New Actions: Added ModernCart cart action configuration.
  • Improvement: Improved product, variation, and cart item selection safety.
  • Fix: Prevented invalid variable product and cart item configurations.

Copilot AI review requested due to automatic review settings July 7, 2026 10:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +1 to +21
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 })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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
  1. 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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
  }
}, [])

Comment on lines +21 to +31
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)
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
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
  1. 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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
})

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

✅ WordPress Plugin Check Report

✅ Status: Passed

📊 Report

All checks passed! No errors or warnings found.


🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants