Skip to content

feat(integrations): add Power Coupons integration#192

Open
RishadAlam wants to merge 7 commits into
mainfrom
feat/power-coupons
Open

feat(integrations): add Power Coupons integration#192
RishadAlam wants to merge 7 commits into
mainfrom
feat/power-coupons

Conversation

@RishadAlam

Copy link
Copy Markdown
Member

Description

This PR adds the Power Coupons for WooCommerce integration to Bit Integrations. It introduces backend authorization and execution support, plus the frontend setup flow for creating, updating, deleting, and toggling Power Coupons coupon settings.

Motivation & Context

Users need a way to connect form or trigger data to Power Coupons coupon operations from Bit Integrations. This integration enables coupon automation through Pro-backed hooks while keeping setup configurable from the existing integration builder UI.

Related Links: (if applicable)

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 📚 Documentation update
  • ⚡ Improvement
  • 🔄 Code refactor

Key Changes

Backend

  • Added Power Coupons controller, route, and record API helper for authorization and action execution.
  • Added support for create coupon, update coupon, delete coupon, toggle auto apply, toggle show in slideout, and toggle rules actions.
  • Added plugin availability checks for WooCommerce and Power Coupons before executing integration actions.
  • Added action response logging for Power Coupons executions.

Frontend

  • Added Power Coupons integration setup screens, authorization step, field mapping, action selection, and utility configuration.
  • Added action-specific field definitions and utility defaults for coupon creation, updates, deletion, and toggle actions.
  • Added validation for required mappings, coupon lookup fields, required utility options, and update payloads.
  • Added Power Coupons to the action/trigger selection flows and webhook integration metadata.

Assets

  • Added Power Coupons integration logo asset.

Checklist

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

Changelog

  • New Actions: Added Power Coupons actions to create, update, delete, and manage coupon settings from automation flows.
  • Feature: Added field mapping and utility options for Power Coupons coupon configuration.
  • Improvement: Added validation to prevent incomplete Power Coupons action setup before saving flows.

Implement Power Coupons for WooCommerce as a new Pro action integration. Includes backend controller with AJAX routes for authorization and coupon retrieval, and complete frontend UI with field mapping, action selection (create, update, delete, toggle), and coupon picker. Supports dynamic field mapping with required/optional field validation.
Reworked the PowerCoupons integration UI by extracting utility controls into a new `PowerCouponsActions` component and centralizing utility option/default config in `staticData`. Removed coupon list refresh/selection flows and shifted update/delete/toggle actions to require `coupon_code` field mapping, with field-map normalization ensuring required fields stay present. Backend routes/controller cleanup removed the unused refresh endpoint, and API payload prep now strips unsupported identifier fields (`coupon_id`/`id`) before sending requests.
Update the PowerCoupons validation message to ask users to map a coupon code, and tidy the field-map normalization formatting in the integration layout.
Copilot AI review requested due to automatic review settings July 9, 2026 05:45

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 'Power Coupons for WooCommerce', adding backend controllers, API helpers, and routes, alongside frontend components for authorization, field mapping, actions, and editing. Feedback on the changes highlights two key improvements: first, simplifying the dependency array of the useEffect hook in PowerCouponsIntegLayout.jsx to prevent potential infinite loops and excessive re-renders caused by updating state properties inside the effect; second, adding validation and a snackbar error message in PowerCoupons.jsx when the integration name is cleared to prevent silent transition blocks.

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 +138 to +174
useEffect(() => {
if (!action || !FIELD_MAP[action]) {
return
}

const normalizedFields = FIELD_MAP[action]
const normalizedFieldMap = normalizeFieldMap(powerCouponsConf?.field_map, normalizedFields)
const normalizedUtilities = normalizeUtilities(
action,
powerCouponsConf?.utilities,
powerCouponsConf?.field_map
)
const fieldsChanged =
JSON.stringify(powerCouponsConf?.powerCouponsFields || []) !== JSON.stringify(normalizedFields)
const fieldMapChanged =
JSON.stringify(powerCouponsConf?.field_map || []) !== JSON.stringify(normalizedFieldMap)
const utilitiesChanged =
JSON.stringify(powerCouponsConf?.utilities || {}) !== JSON.stringify(normalizedUtilities)

if (!fieldsChanged && !fieldMapChanged && !utilitiesChanged) {
return
}

setPowerCouponsConf(prevConf =>
create(prevConf, draftConf => {
draftConf.powerCouponsFields = normalizedFields
draftConf.field_map = normalizedFieldMap
draftConf.utilities = normalizedUtilities
})
)
}, [
action,
powerCouponsConf?.field_map,
powerCouponsConf?.powerCouponsFields,
powerCouponsConf?.utilities,
setPowerCouponsConf
])

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

The useEffect hook has powerCouponsConf?.field_map, powerCouponsConf?.powerCouponsFields, and powerCouponsConf?.utilities in its dependency array, but it also updates these exact same state properties inside the effect. This creates a risk of infinite loops, excessive re-renders, and cursor jumping/lag when typing custom values or changing field mappings.

Since normalization is only required when the action changes or on initial mount, the dependency array should be simplified to only depend on action and setPowerCouponsConf.

  useEffect(() => {
    if (!action || !FIELD_MAP[action]) {
      return
    }

    setPowerCouponsConf(prevConf =>
      create(prevConf, draftConf => {
        draftConf.powerCouponsFields = FIELD_MAP[action]
        draftConf.field_map = normalizeFieldMap(draftConf.field_map, FIELD_MAP[action])
        draftConf.utilities = normalizeUtilities(action, draftConf.utilities, draftConf.field_map)
      })
    )
  }, [action, setPowerCouponsConf])
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. The normalization effect now only depends on the selected action and setter, and reads the current draft state inside the state updater before deciding whether anything needs to change.

setPowerCouponsConf(prevConf =>
  create(prevConf, draftConf => {
    const normalizedFields = FIELD_MAP[action]
    const normalizedFieldMap = normalizeFieldMap(draftConf.field_map, normalizedFields)
    const normalizedUtilities = normalizeUtilities(action, draftConf.utilities, draftConf.field_map)

    if (!fieldsChanged && !fieldMapChanged && !utilitiesChanged) {
      return
    }

    draftConf.powerCouponsFields = normalizedFields
    draftConf.field_map = normalizedFieldMap
    draftConf.utilities = normalizedUtilities
  })
)

Comment on lines +79 to +81
if (powerCouponsConf.name !== '' && powerCouponsConf.field_map.length > 0) {
setStep(val)
}

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

If the user clears the integration name and clicks "Next", the step transition is silently blocked without displaying any error message. This can be confusing for the user. We should validate that the integration name is not empty and show a snackbar error message if it is.

      if (!powerCouponsConf.name) {
        setSnackbar({
          show: true,
          msg: __('Integration name cannot be empty.', 'bit-integrations')
        })
        return
      }

      if (powerCouponsConf.field_map.length > 0) {
        setStep(val)
      }
References
  1. Use falsy checks (e.g., !value) instead of strict equality checks against undefined when validating configuration or form fields, to ensure that null or empty string values are also correctly identified as incomplete.

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. Empty integration names now show a snackbar message instead of silently blocking the step transition.

if (!powerCouponsConf.name) {
  setSnackbar({
    show: true,
    msg: __('Integration name cannot be empty.', 'bit-integrations')
  })
  return
}

@github-actions

github-actions Bot commented Jul 9, 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

Copilot AI review requested due to automatic review settings July 9, 2026 05:58

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.

Copilot AI review requested due to automatic review settings July 14, 2026 05:10

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.

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