Skip to content

Conversation

@akanshaaa19
Copy link
Member

@akanshaaa19 akanshaaa19 commented Nov 11, 2025

Summary by CodeRabbit

  • New Features

    • WhatsApp Forms: create/edit flows, list with filters, publish/activate/deactivate, multi-category tags, quick Flow Builder access, new menu entry and icon, plus chat view for form responses.
    • HSM/Template options: new "WhatsApp Form" button type and UI to pick forms/screens.
  • Tests

    • Integration and e2e tests covering list, create/edit, publish/deactivate, chat response display, and HSM/template flows.
  • UI & Translations

    • New styling for forms/list/templates and added translation keys for form UI.

✏️ Tip: You can customize this high-level summary in your review settings.

…omponents (#3607)

* feat: add WhatsApp Forms feature with CRUD operations and UI components

* fix: correct SVG attribute casing in WhatsAppForms component

* fix: correct component name from WhatsAppForms to WhatsAppForm for consistency

* feat: update WhatsAppForms component with new queries and edit route

* feat: ✨ Move WhatsApp Forms menu item and add service-based
visibility

The WhatsApp Forms menu item is now positioned earlier in the menu order
and includes a visibility condition based on the whatsappFormsEnabled
organization service setting.

* feat: refactor WhatsAppForms component to use formJson and formCategories, add error handling for JSON parsing

* feat: add FlowBuilderInfo section with guidance and button to open Meta Flow Builder in WhatsAppForms component

* feat: add tests for WhatsAppForms component and mock data for form handling

* fix: add missing newline at end of WhatsAppForm.module.css

---------

Co-authored-by: Shijith <[email protected]>
@coderabbitai
Copy link

coderabbitai bot commented Nov 11, 2025

Walkthrough

Adds end-to-end WhatsApp Forms support: new UI components (form builder, list, response view, icons, CSS), GraphQL queries/mutations/subscriptions for CRUD and status transitions, route and menu wiring, HSM and TemplateOptions integration to support a new WHATSAPP_FORM button type, new constants and service flag, updated mocks/tests across many suites, minor List typing change, i18n key adjustments, and a GitHub Actions branch checkout change.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Areas needing extra attention:
    • src/containers/WhatsAppForms/WhatsAppForms.tsx — JSON parsing, validation, and mutation payload construction
    • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx — per-item actions, confirmation dialogs, and mutation handling
    • HSM surface changes: src/containers/HSM/HSM.tsx and src/containers/HSM/HSM.helper.ts — new button type, payload generation, and validation
    • TemplateOptions and TemplateOptions.tsx — UI wiring, GraphQL usage, and dependent state handling (screens from form definitions)
    • Tests and mocks: src/mocks/WhatsAppForm.tsx and many updated test suites — ensure mocks cover both success and error paths and that test index/selector changes remain correct
    • Chat integration: SEARCH_QUERY, subscriptions, ChatMessage and WhatsAppFormResponse parsing/rendering

Possibly related PRs

Suggested labels

status: ready for review

Suggested reviewers

  • shijithkjayan
  • priyanshu6238
  • madclaws

Poem

🐰 I hopped through code with tiny paws,
Sprinkled forms and GraphQL laws,
Icons, tests, and routes aligned,
A leafy feature — neatly signed,
Carrot-cookie deploy applause.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Whatsapp Forms' is overly broad and vague, using a generic term that doesn't convey the specific nature of changes (e.g., new feature, refactor, or component addition). Consider using a more descriptive title such as 'Add WhatsApp Forms feature' or 'Implement WhatsApp form builder and management' to better convey the scope and primary changes in this comprehensive PR.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/whatsapp-forms

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a5e169 and 0edf13d.

📒 Files selected for processing (1)
  • src/i18n/en/en.json (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: build
  • GitHub Check: glific (1.18.3-otp-27, 27.3.3)
  • GitHub Check: CI
🔇 Additional comments (1)
src/i18n/en/en.json (1)

13-14: Previous duplicate issue resolved; changes LGTM.

The previously flagged duplicate "Last Updated" key has been properly removed from its later occurrence in the file. Both new keys ("Form Name" and "Last Updated") are now unique and appropriately support the WhatsApp Forms UI components referenced in the PR.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Nov 11, 2025

@github-actions github-actions bot temporarily deployed to pull request November 11, 2025 17:31 Inactive
@github-actions github-actions bot temporarily deployed to pull request November 11, 2025 17:33 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (4)
src/graphql/queries/WhatsAppForm.ts (1)

21-25: Add an operation name to the query.

The query lacks an operation name, which is recommended for better debugging and tooling support.

Apply this diff:

 export const LIST_FORM_CATEGORIES = gql`
-  query {
+  query WhatsappFormCategories {
     whatsappFormCategories
   }
 `;
src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx (1)

7-30: Complete the list implementation.

The component currently renders only a header and placeholder text. The TODO comment indicates that the actual <List /> component needs to be integrated to display the WhatsApp Forms list.

Do you want me to help implement the list component integration or track this as a separate issue?

src/containers/WhatsAppForms/WhatsAppForms.tsx (2)

27-37: Improve type safety and variable declarations.

Two minor improvements:

  1. Line 30: formJson state lacks a type annotation, reducing type safety.
  2. Line 34: isEditing should be const since it's never reassigned.

Apply this diff:

- const [formJson, setFormJson] = useState();
+ const [formJson, setFormJson] = useState<any>();
  const [formCategories, setFormCategories] = useState([]);
  const [categories, setCategories] = useState([]);
  const params = useParams();
- let isEditing = false;
+ const isEditing = !!params.id;
- if (params.id) {
-   isEditing = true;
- }

140-140: Remove unused variable.

The dialogMessage variable is declared but never assigned a value or used. Consider removing it if it's not needed, or implement it if it's meant for future functionality.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b7e0c2 and eaaa41e.

📒 Files selected for processing (14)
  • src/assets/images/icons/SideDrawer/WhatsappForm.tsx (1 hunks)
  • src/common/HelpData.tsx (1 hunks)
  • src/components/UI/ListIcon/ListIcon.tsx (2 hunks)
  • src/config/menu.ts (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppForm.module.css (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppForm.test.tsx (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppForms.tsx (1 hunks)
  • src/graphql/mutations/WhatsAppForm.ts (1 hunks)
  • src/graphql/queries/Organization.ts (1 hunks)
  • src/graphql/queries/WhatsAppForm.ts (1 hunks)
  • src/mocks/WhatsApp.tsx (1 hunks)
  • src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx (2 hunks)
  • src/services/AuthService.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

Files:

  • src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx
  • src/graphql/queries/WhatsAppForm.ts
  • src/graphql/mutations/WhatsAppForm.ts
  • src/assets/images/icons/SideDrawer/WhatsappForm.tsx
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx
  • src/common/HelpData.tsx
  • src/containers/WhatsAppForms/WhatsAppForm.test.tsx
  • src/config/menu.ts
  • src/graphql/queries/Organization.ts
  • src/mocks/WhatsApp.tsx
  • src/components/UI/ListIcon/ListIcon.tsx
  • src/containers/WhatsAppForms/WhatsAppForms.tsx
  • src/services/AuthService.tsx
🧬 Code graph analysis (6)
src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx (1)
src/containers/WhatsAppForms/WhatsAppForms.tsx (1)
  • WhatsAppForms (27-197)
src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx (3)
src/components/UI/HelpIcon/HelpIcon.tsx (1)
  • HelpIcon (12-54)
src/common/HelpData.tsx (1)
  • whatsappFormsInfo (143-146)
src/components/UI/Form/Button/Button.tsx (1)
  • Button (12-29)
src/containers/WhatsAppForms/WhatsAppForm.test.tsx (3)
src/mocks/WhatsApp.tsx (2)
  • WHATSAPP_FORM_MOCKS (124-129)
  • formJson (4-22)
src/containers/WhatsAppForms/WhatsAppForms.tsx (1)
  • WhatsAppForms (27-197)
src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx (1)
  • WhatsAppFormList (7-30)
src/config/menu.ts (1)
src/services/AuthService.tsx (1)
  • getOrganizationServices (187-192)
src/mocks/WhatsApp.tsx (2)
src/graphql/queries/WhatsAppForm.ts (2)
  • LIST_FORM_CATEGORIES (21-25)
  • GET_WHATSAPP_FORM (3-19)
src/graphql/mutations/WhatsAppForm.ts (2)
  • CREATE_FORM (3-15)
  • UPDATE_FORM (17-29)
src/containers/WhatsAppForms/WhatsAppForms.tsx (8)
src/graphql/queries/WhatsAppForm.ts (2)
  • GET_WHATSAPP_FORM (3-19)
  • LIST_FORM_CATEGORIES (21-25)
src/graphql/mutations/WhatsAppForm.ts (3)
  • CREATE_FORM (3-15)
  • UPDATE_FORM (17-29)
  • DELETE_FORM (31-43)
src/components/UI/Form/Input/Input.tsx (1)
  • Input (34-154)
src/components/UI/Form/AutoComplete/AutoComplete.tsx (1)
  • AutoComplete (46-281)
src/components/UI/Layout/Loading/Loading.tsx (1)
  • Loading (14-41)
src/components/UI/Heading/Heading.tsx (1)
  • Heading (23-59)
src/common/HelpData.tsx (1)
  • whatsappFormsInfo (143-146)
src/components/UI/Form/Button/Button.tsx (1)
  • Button (12-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: glific (1.18.3-otp-27, 27.3.3)
  • GitHub Check: CI
  • GitHub Check: build
🔇 Additional comments (19)
src/graphql/queries/Organization.ts (1)

139-139: LGTM!

The addition of whatsappFormsEnabled to the organization services query is consistent with the existing service flag pattern and integrates cleanly with the feature flag infrastructure.

src/components/UI/ListIcon/ListIcon.tsx (2)

37-37: LGTM!

The import and icon mapping for WhatsApp Forms follows the established pattern and integrates cleanly with the existing icon system.


83-83: LGTM!

The form icon mapping is correctly registered in the icon dictionary.

src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx (2)

71-72: LGTM!

The lazy-loaded imports for WhatsApp Forms components follow the established pattern and enable proper code splitting.


164-168: LGTM!

The route configuration for WhatsApp Forms is well-structured with proper nested routes for list, add, and edit operations, consistent with other features like certificates and polls.

src/services/AuthService.tsx (1)

23-24: LGTM!

The ServiceType union is correctly extended to include 'whatsappFormsEnabled', enabling type-safe access to the WhatsApp Forms service flag throughout the application.

src/containers/WhatsAppForms/WhatsAppForm.test.tsx (1)

1-86: LGTM!

The test suite provides good coverage of the WhatsApp Forms functionality:

  • Initial render and loading states
  • Form validation (including JSON validation)
  • Create flow with field interactions and autocomplete
  • Edit flow with pre-populated data

The tests follow established testing patterns and use appropriate assertions. The JSON validation test correctly verifies that invalid JSON triggers an error before proceeding with valid input.

src/assets/images/icons/SideDrawer/WhatsappForm.tsx (1)

1-23: LGTM!

The WhatsApp Form icon component is correctly implemented:

  • Accepts and applies the color prop appropriately
  • Uses currentColor for stroke, which will inherit from the color attribute
  • SVG attributes are properly camelCased for React
  • Consistent with other icon components in the codebase
src/graphql/queries/WhatsAppForm.ts (1)

3-19: LGTM!

The query structure is correct and field selection is comprehensive for fetching WhatsApp form details.

src/mocks/WhatsApp.tsx (1)

4-129: LGTM!

The mock data structure is consistent with the GraphQL queries and mutations, and provides comprehensive test coverage for form creation, retrieval, and updates.

src/graphql/mutations/WhatsAppForm.ts (1)

3-29: LGTM!

The CREATE_FORM and UPDATE_FORM mutations are well-structured and consistent.

src/containers/WhatsAppForms/WhatsAppForm.module.css (1)

1-76: LGTM!

The CSS module provides well-structured styling for the Flow Builder UI with appropriate visual feedback (hover effects, transitions) and modern layout techniques.

src/containers/WhatsAppForms/WhatsAppForms.tsx (7)

39-51: LGTM!

The category fetching and transformation logic correctly converts snake_case categories to user-friendly Title Case format.


53-58: LGTM!

The states object correctly aggregates form state for the FormLayout component.


60-69: LGTM!

The payload transformation correctly maps form categories to their IDs for API submission.


70-84: Potential inconsistency in category mapping.

Line 74 maps categories to { id: c, name: c }, where both id and name are the same raw category string. However, the categories list from lines 42-48 uses id as snake_case and name as Title Case. This inconsistency might cause display issues or selection problems in the AutoComplete component.

Verify that the AutoComplete component correctly matches these category objects. Consider applying the same transformation used when loading categories:

- setFormCategories(categories.map((c: string) => ({ id: c, name: c })));
+ setFormCategories(
+   categories.map((c: string) => ({
+     id: c,
+     name: c
+       .toLowerCase()
+       .replace(/_/g, ' ')
+       .replace(/\b\w/g, (char) => char.toUpperCase()),
+   }))
+ );

85-121: LGTM!

The form field definitions are well-structured with appropriate input types, placeholders, and helper text.


122-138: LGTM!

The validation schema is well-defined with appropriate constraints for all required fields. The custom JSON validation test is a good addition.


145-196: LGTM!

The component rendering logic is well-structured with appropriate loading states, helpful UI hints for the Meta Flow Builder, and secure external link handling.

@codecov
Copy link

codecov bot commented Nov 11, 2025

Codecov Report

❌ Patch coverage is 76.98113% with 61 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.35%. Comparing base (fbfbe60) to head (0edf13d).

Files with missing lines Patch % Lines
...hatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx 78.65% 13 Missing and 6 partials ⚠️
...sage/WhatsappFormResponse/WhatsAppFormResponse.tsx 5.88% 16 Missing ⚠️
src/containers/TemplateOptions/TemplateOptions.tsx 80.43% 3 Missing and 6 partials ⚠️
src/containers/WhatsAppForms/WhatsAppForms.tsx 86.66% 4 Missing and 2 partials ⚠️
src/containers/HSM/HSM.helper.ts 33.33% 3 Missing and 1 partial ⚠️
src/containers/HSM/HSM.tsx 83.33% 0 Missing and 4 partials ⚠️
...ners/Chat/ChatMessages/ChatMessage/ChatMessage.tsx 0.00% 1 Missing and 1 partial ⚠️
...rc/assets/images/icons/SideDrawer/WhatsappForm.tsx 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3624      +/-   ##
==========================================
- Coverage   82.55%   82.35%   -0.20%     
==========================================
  Files         341      348       +7     
  Lines       11416    11648     +232     
  Branches     2415     2451      +36     
==========================================
+ Hits         9424     9593     +169     
- Misses       1260     1313      +53     
- Partials      732      742      +10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cypress
Copy link

cypress bot commented Nov 11, 2025

Glific    Run #6659

Run Properties:  status check failed Failed #6659  •  git commit 235d0eeacf ℹ️: Merge 32e66c4a94c6d11cd1f34a6dc71460742b7934b5 into c7c6dbacd4b93b08a2133ba88aac...
Project Glific
Branch Review feat/whatsapp-forms
Run status status check failed Failed #6659
Run duration 44m 42s
Commit git commit 235d0eeacf ℹ️: Merge 32e66c4a94c6d11cd1f34a6dc71460742b7934b5 into c7c6dbacd4b93b08a2133ba88aac...
Committer Akansha Sakhre
View all properties for this run ↗︎

Test results
Tests that failed  Failures 42
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 0
Tests that did not run due to a failure in a mocha hook  Skipped 27
Tests that passed  Passing 113
View all changes introduced in this branch ↗︎

Tests for review

Failed  chat/Chat.spec.ts • 15 failed tests

View Output

Test Artifacts
Chats > starts simulator and send message from it Test Replay Screenshots
Chats > should send the message correctly Test Replay Screenshots
Chats > should send the emoji in message Test Replay Screenshots
Chats > should send the speed send Test Replay Screenshots
Chats > should send the templates Test Replay Screenshots
Chats > should send add to speed send Test Replay Screenshots
Chats > Send attachment - Image Test Replay Screenshots
Chats > Send attachment - Audio Test Replay Screenshots
Chats > Send attachment - Video Test Replay Screenshots
Chats > Send attachment - Document Test Replay Screenshots
The first 10 failed tests are shown, see all 15 tests in Cypress Cloud.
Failed  chat/ChatCollection.spec.ts • 1 failed test

View Output

Test Artifacts
ChatCollection > should send the message to collection Test Replay Screenshots
Failed  chat/Search.spec.ts • 4 failed tests

View Output

Test Artifacts
Search > should search in chat search Test Replay Screenshots
Search > should check unread messages Test Replay Screenshots
Search > Select searched contact Test Replay Screenshots
Search > Advanced search with name/tag/keyword Test Replay Screenshots
Failed  contactBar/ContactBar.spec.ts • 6 failed tests

View Output

Test Artifacts
Contact bar > should view contact profile Test Replay Screenshots
Contact bar > should start a flow Test Replay Screenshots
Contact bar > should add to collection Test Replay Screenshots
Contact bar > should remove from collection Test Replay Screenshots
Contact bar > should block contact Test Replay Screenshots
Contact bar > should clear conversations Test Replay Screenshots
Failed  flow/FlowEditor.spec.ts • 1 failed test

View Output

Test Artifacts
Flow > should configure Flow Test Replay Screenshots

The first 5 failed specs are shown, see all 11 specs in Cypress Cloud.

@github-actions github-actions bot temporarily deployed to pull request November 13, 2025 03:07 Inactive
@github-actions github-actions bot temporarily deployed to pull request November 14, 2025 10:29 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
src/containers/Chat/ChatMessages/ChatMessage/WhatsappFormResponse/WhatsAppFormResponse.tsx (1)

54-62: Refactor inline styles to CSS modules and add null handling.

  1. Move inline styles to the CSS module for consistency
  2. Handle null/undefined values properly
-              {Object.entries(parsedResponse).map(([key, value]) => (
-                <div key={key} style={{ marginBottom: '8px' }}>
-                  <Typography variant="subtitle2" style={{ fontWeight: 'bold' }}>
+              {Object.entries(parsedResponse).map(([key, value]) => (
+                <div key={key} className={styles.ResponseItem}>
+                  <Typography variant="subtitle2" className={styles.ResponseKey}>
                     {key}:
                   </Typography>
                   <Typography variant="body2">
-                    {typeof value === 'object' ? JSON.stringify(value, null, 2) : String(value)}
+                    {value == null ? 'N/A' : typeof value === 'object' ? JSON.stringify(value, null, 2) : String(value)}
                   </Typography>
                 </div>
               ))}

Add to CSS module:

.ResponseItem {
    margin-bottom: 8px;
}

.ResponseKey {
    font-weight: bold;
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 41aa284 and 6c7c220.

📒 Files selected for processing (4)
  • src/containers/Chat/ChatMessages/ChatMessage/ChatMessage.tsx (4 hunks)
  • src/containers/Chat/ChatMessages/ChatMessage/WhatsappFormResponse/WhatsAppFormResponse.module.css (1 hunks)
  • src/containers/Chat/ChatMessages/ChatMessage/WhatsappFormResponse/WhatsAppFormResponse.tsx (1 hunks)
  • src/graphql/queries/Search.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

Files:

  • src/containers/Chat/ChatMessages/ChatMessage/WhatsappFormResponse/WhatsAppFormResponse.tsx
  • src/graphql/queries/Search.ts
  • src/containers/Chat/ChatMessages/ChatMessage/ChatMessage.tsx
🧬 Code graph analysis (2)
src/containers/Chat/ChatMessages/ChatMessage/WhatsappFormResponse/WhatsAppFormResponse.tsx (1)
src/components/UI/DialogBox/DialogBox.tsx (1)
  • DialogBox (32-149)
src/containers/Chat/ChatMessages/ChatMessage/ChatMessage.tsx (1)
src/containers/Chat/ChatMessages/ChatMessage/WhatsappFormResponse/WhatsAppFormResponse.tsx (1)
  • WhatsAppFormResponse (11-72)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: glific (1.18.3-otp-27, 27.3.3)
  • GitHub Check: build
  • GitHub Check: CI
🔇 Additional comments (4)
src/graphql/queries/Search.ts (1)

72-75: LGTM!

The addition of whatsappFormResponse field to the query is properly structured and aligns with the WhatsApp Forms feature requirements.

src/containers/Chat/ChatMessages/ChatMessage/ChatMessage.tsx (2)

29-29: LGTM!

The import statement is correct and follows the existing import patterns in the file.


336-343: LGTM!

The rendering logic for WhatsApp form responses follows the established pattern for other message types and correctly passes the raw response data to the component.

src/containers/Chat/ChatMessages/ChatMessage/WhatsappFormResponse/WhatsAppFormResponse.module.css (1)

1-26: LGTM!

The CSS module is well-structured with appropriate styles for the WhatsApp form response UI component.

@github-actions github-actions bot temporarily deployed to pull request November 17, 2025 05:52 Inactive
* feat: add WhatsApp Forms feature with CRUD operations and UI components

* fix: correct SVG attribute casing in WhatsAppForms component

* fix: correct component name from WhatsAppForms to WhatsAppForm for consistency

* feat: update WhatsAppForms component with new queries and edit route

* feat: ✨ Move WhatsApp Forms menu item and add service-based
visibility

The WhatsApp Forms menu item is now positioned earlier in the menu order
and includes a visibility condition based on the whatsappFormsEnabled
organization service setting.

* feat: refactor WhatsAppForms component to use formJson and formCategories, add error handling for JSON parsing

* feat: add FlowBuilderInfo section with guidance and button to open Meta Flow Builder in WhatsAppForms component

* feat: add tests for WhatsAppForms component and mock data for form handling

* feat: add listing ui for whatsapp form

* fix: css

* refactor: remove unused css

* fix: css and remove screen debug function from test case

* fix: deep scan

* refactor: add status field in the column

* reafctor: add test case

* fix:test case

* refactor: add mock

* reafctor: add deactivate option

* reafctor: add + symbol for category

* refactor: add dialog box

* fix: first test case

* fix: test case

* fix: add test case

* fix : deep scan

* refactor: add hover to the + more option

* fix: css and cypress

* refactor: rename dialog message

* fix: add delete api

* fix: css

* fix: css

* fix: css

* fix: css

* fix: naming

---------

Co-authored-by: Akansha Sakhre <[email protected]>
Co-authored-by: Shijith <[email protected]>
@github-actions github-actions bot temporarily deployed to pull request November 17, 2025 08:12 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (3)
src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx (3)

54-63: Rename InactiveItem to deactivateItem for consistency.

The function name should match the action it performs and align with the naming pattern of publishItem.

Apply this diff:

- const InactiveItem = async (item: any) => {
+ const deactivateItem = async (item: WhatsAppForm) => {
    try {
      await deactivateForm({
        variables: { id: item.id },
      });
      setNotification('Form deactivated successfully');
    } catch (error) {
      setErrorMessage(error);
    }
  };

Also update the call site at line 194:

      if (dialogType === 'publish') {
        publishItem(currentItem);
      } else if (dialogType === 'inactive') {
-       InactiveItem(currentItem);
+       deactivateItem(currentItem);
      }

178-178: Avoid variable shadowing in the map function.

The variable name filter in the map callback shadows the outer filter state variable, which can cause confusion.

Apply this diff:

-         {filterList.map((filter: any) => (
-           <MenuItem key={filter.label} value={filter.value}>
-             {filter.label}
+         {filterList.map((filterOption) => (
+           <MenuItem key={filterOption.label} value={filterOption.value}>
+             {filterOption.label}
            </MenuItem>
          ))}

151-163: Add proper typing for the filters object.

The filters variable uses any type, reducing type safety.

Apply this diff:

  const filters = useMemo(() => {
-   let filters: any = {};
+   let filters: { status?: 'PUBLISHED' | 'DRAFT' | 'INACTIVE' } = {};

    if (filter === 'published') {
      filters = { status: 'PUBLISHED' };
    } else if (filter === 'draft') {
      filters = { status: 'DRAFT' };
    } else if (filter === 'inactive') {
      filters = { status: 'INACTIVE' };
    }

    return filters;
  }, [filter]);
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7aa46fe and 32e66c4.

⛔ Files ignored due to path filters (2)
  • src/assets/images/icons/DeactivateIcon.svg is excluded by !**/*.svg
  • src/assets/images/icons/PublishGood.svg is excluded by !**/*.svg
📒 Files selected for processing (9)
  • .github/workflows/cypress-testing.yml (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppForm.module.css (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.module.css (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.test.tsx (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx (1 hunks)
  • src/graphql/mutations/WhatsAppForm.ts (1 hunks)
  • src/graphql/queries/WhatsAppForm.ts (1 hunks)
  • src/i18n/en/en.json (1 hunks)
  • src/mocks/WhatsApp.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.module.css
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

Files:

  • src/mocks/WhatsApp.tsx
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx
  • src/graphql/queries/WhatsAppForm.ts
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.test.tsx
  • src/graphql/mutations/WhatsAppForm.ts
🧬 Code graph analysis (3)
src/mocks/WhatsApp.tsx (2)
src/graphql/queries/WhatsAppForm.ts (3)
  • LIST_FORM_CATEGORIES (21-25)
  • LIST_WHATSAPP_FORMS (27-39)
  • GET_WHATSAPP_FORM (3-19)
src/graphql/mutations/WhatsAppForm.ts (4)
  • CREATE_FORM (3-15)
  • PUBLISH_FORM (50-67)
  • DEACTIVATE_FORM (69-82)
  • UPDATE_FORM (17-29)
src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx (4)
src/graphql/queries/WhatsAppForm.ts (2)
  • LIST_WHATSAPP_FORMS (27-39)
  • GET_WHATSAPP_FORM (3-19)
src/graphql/mutations/WhatsAppForm.ts (3)
  • DELETE_FORM (31-48)
  • PUBLISH_FORM (50-67)
  • DEACTIVATE_FORM (69-82)
src/components/UI/DialogBox/DialogBox.tsx (1)
  • DialogBox (32-149)
src/common/HelpData.tsx (1)
  • whatsappFormsInfo (143-146)
src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.test.tsx (2)
src/mocks/WhatsApp.tsx (5)
  • WHATSAPP_FORM_MOCKS (275-284)
  • publishWhatsappForm (69-85)
  • publishWhatsappFormError (104-112)
  • deactivateWhatsappForm (87-103)
  • deactivateWhatsappFormError (114-122)
src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx (1)
  • WhatsAppFormList (24-242)
🪛 Biome (2.1.2)
src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.test.tsx

[error] 15-16: Do not export from a test file.

(lint/suspicious/noExportsInTest)

src/i18n/en/en.json

[error] 14-14: The key Last Updated was already declared.

This where a duplicated key was declared again.

If a key is defined multiple times, only the last definition takes effect. Previous definitions are ignored.

(lint/suspicious/noDuplicateObjectKeys)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: build
  • GitHub Check: glific (1.18.3-otp-27, 27.3.3)
  • GitHub Check: CI
🔇 Additional comments (3)
src/graphql/queries/WhatsAppForm.ts (1)

1-39: LGTM!

The GraphQL queries are well-structured with appropriate field selections that align with the feature requirements and mock data.

src/graphql/mutations/WhatsAppForm.ts (1)

1-82: LGTM!

All five mutations are properly structured with correct operation names, variables, and response shapes that align with the expected GraphQL schema.

src/containers/WhatsAppForms/WhatsAppForm.module.css (1)

1-75: LGTM!

The CSS module is well-structured with modern styling patterns, smooth transitions, and consistent visual hierarchy.

* Add WhatsApp form icons and update styles; refactor form-related tests and mocks

* Refactor dialog handling in WhatsAppFormList component; improve delete, publish, and deactivate confirmation messages

* minor fixes

* remove null check

* added error message

* fixed test cases
@github-actions github-actions bot temporarily deployed to pull request November 18, 2025 14:45 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
src/mocks/WhatsAppForm.tsx (1)

69-102: Align publish/deactivate mocks with mutation schema (field name + response shape)

Both mutation mocks here diverge from the GraphQL schema:

  • publishWhatsappForm mock (Lines 69–84) should wrap the form in whatsappForm and include errors, per PUBLISH_FORM.
  • deactivateWhatsappForm mock (Lines 86–102) uses the wrong root field name (publishWhatsappForm) and returns a flat object with lowercase status, instead of deactivateWhatsappForm.whatsappForm.status.

This can easily trip up future code/tests that expect the schema shape (e.g., data.deactivateWhatsappForm.whatsappForm.status), and it contradicts the documented mutations.

Consider updating both mocks like this:

 export const publishWhatsappForm = {
   request: {
     query: PUBLISH_FORM,
     variables: {
       id: '3',
     },
   },
   result: {
     data: {
-      publishWhatsappForm: {
-        id: '1',
-        status: 'PUBLISHED',
-      },
+      publishWhatsappForm: {
+        whatsappForm: {
+          id: '1',
+          status: 'PUBLISHED',
+        },
+        errors: null,
+      },
     },
   },
 };

 export const deactivateWhatsappForm = {
   request: {
     query: DEACTIVATE_FORM,
     variables: {
       id: '3',
     },
   },
   result: {
     data: {
-      publishWhatsappForm: {
-        id: '1',
-        status: 'inactive',
-        __typename: 'WhatsappForm',
-      },
+      deactivateWhatsappForm: {
+        whatsappForm: {
+          id: '1',
+          status: 'INACTIVE',
+        },
+        errors: null,
+      },
     },
   },
 };

This keeps mocks faithful to the schema and avoids subtle bugs if result data is ever accessed instead of just side effects.

src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.test.tsx (1)

16-16: Remove unnecessary export from the test file

This test file shouldn’t re-export mocks; it’s meant to be a leaf module, and Biome is already flagging this. The tests use the imported mocks directly, so the export is redundant.

Apply:

-import { WhatsAppFormList } from './WhatsAppFormList';
-
-export { publishWhatsappForm, publishWhatsappFormError } from 'mocks/WhatsAppForm';
-
-const mockNavigate = vi.fn();
+import { WhatsAppFormList } from './WhatsAppFormList';
+
+const mockNavigate = vi.fn();
🧹 Nitpick comments (6)
src/containers/List/List.tsx (1)

126-134: additionalAction icon optionality matches usage; consider tightening action typing

Making icon optional is correct given some actions (e.g., WhatsApp forms activate/deactivate) are text-only and React safely renders undefined icons. You may also want to extend this inline type to cover other properties actually used in List (hidden?, insideMore?) so call sites get better TS help when building action objects, but that’s a nicety, not a blocker.

src/graphql/mutations/WhatsAppForm.ts (2)

44-56: Inconsistent mutation naming convention.

The mutation name publishWhatsappForm uses a lowercase 'p', while other mutations in this file follow the pattern CreateWhatsappForm, UpdateWhatsappForm, DeleteWhatsappForm, and DeactivateWhatsappForm (all capitalized).

Consider standardizing to PublishWhatsappForm for consistency:

 export const PUBLISH_FORM = gql`
-  mutation publishWhatsappForm($id: ID!) {
+  mutation PublishWhatsappForm($id: ID!) {
     publishWhatsappForm(id: $id) {
       whatsappForm {
         id
         status
       }
       errors {
         message
       }
     }
   }
 `;

Verify that the backend schema supports the capitalized mutation name, or document if the lowercase naming is required by the backend.


72-91: Inconsistent variable naming and extensive field selection.

Two observations:

  1. Variable naming: The variable is named $activateWhatsappFormId while all other mutations in this file use $id. This breaks the established pattern and adds unnecessary verbosity.

  2. Field selection: This mutation returns 9 fields (categories, definition, description, id, insertedAt, metaFlowId, name, status, updatedAt) while other mutations return only 2-3 fields.

For consistency, consider renaming the variable:

 export const ACTIVATE_FORM = gql`
-  mutation ActivateWhatsappForm($activateWhatsappFormId: ID!) {
-    activateWhatsappForm(id: $activateWhatsappFormId) {
+  mutation ActivateWhatsappForm($id: ID!) {
+    activateWhatsappForm(id: $id) {
       whatsappForm {
         categories
         definition
         description
         id
         insertedAt
         metaFlowId
         name
         status
         updatedAt
       }
       errors {
         message
       }
     }
   }
 `;

Verify whether the extensive field selection is intentional (e.g., to update the UI after activation) or if it should be reduced to match other mutations (id, status, errors) for consistency.

src/containers/WhatsAppForms/WhatsAppForms.tsx (3)

46-49: Simplify boolean logic.

The isEditing assignment is unnecessarily verbose.

Apply this diff to simplify:

-  let isEditing = false;
-  if (params.id) {
-    isEditing = true;
-  }
+  const isEditing = Boolean(params.id);

72-81: Replace any type with proper TypeScript interface.

The setPayload function uses any type, which defeats TypeScript's type safety benefits.

Define a proper interface for the form data:

interface WhatsAppFormData {
  name: string;
  formJson: string;
  formCategories: Array<{ id: string; name: string }>;
  description: string;
}

Then apply this diff:

-  const setPayload = ({ name, formJson, formCategories, description }: any) => {
+  const setPayload = ({ name, formJson, formCategories, description }: WhatsAppFormData) => {
     const payload = {
       name,
       formJson,
       description,
       categories: formCategories.map((category: any) => category.id),
     };

     return payload;
   };

Also remove the any type from the map callback:

-      categories: formCategories.map((category: any) => category.id),
+      categories: formCategories.map((category) => category.id),

175-191: Simplify button implementation.

The button uses component="a" (line 180) combined with an onClick handler (line 181), which is unconventional. When using onClick with window.open, the component="a" prop is unnecessary.

Apply this diff to simplify:

         <Button
           color="primary"
           variant="contained"
           className={styles.FlowBuilderButton}
           startIcon={<OpenInNew />}
-          component="a"
           onClick={() =>
             window.open(
               'https://developers.facebook.com/docs/whatsapp/flows/playground',
               '_blank',
               'noopener,noreferrer'
             )
           }
         >
           Open Flow Builder
         </Button>

Alternatively, extract the handler to a separate function for better readability:

const handleOpenFlowBuilder = () => {
  window.open(
    'https://developers.facebook.com/docs/whatsapp/flows/playground',
    '_blank',
    'noopener,noreferrer'
  );
};

// In JSX:
<Button
  color="primary"
  variant="contained"
  className={styles.FlowBuilderButton}
  startIcon={<OpenInNew />}
  onClick={handleOpenFlowBuilder}
>
  Open Flow Builder
</Button>
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32e66c4 and 4b91823.

⛔ Files ignored due to path filters (2)
  • src/assets/images/icons/Publish/PublishGray.svg is excluded by !**/*.svg
  • src/assets/images/icons/Publish/PublishWhite.svg is excluded by !**/*.svg
📒 Files selected for processing (11)
  • src/components/floweditor/FlowEditor.tsx (1 hunks)
  • src/containers/List/List.tsx (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppForm.module.css (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppForm.test.tsx (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.module.css (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.test.tsx (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx (1 hunks)
  • src/containers/WhatsAppForms/WhatsAppForms.tsx (1 hunks)
  • src/graphql/mutations/WhatsAppForm.ts (1 hunks)
  • src/i18n/en/en.json (1 hunks)
  • src/mocks/WhatsAppForm.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/components/floweditor/FlowEditor.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx
  • src/containers/WhatsAppForms/WhatsAppForm.test.tsx
  • src/i18n/en/en.json
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

Files:

  • src/containers/List/List.tsx
  • src/mocks/WhatsAppForm.tsx
  • src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.test.tsx
  • src/containers/WhatsAppForms/WhatsAppForms.tsx
  • src/graphql/mutations/WhatsAppForm.ts
🧬 Code graph analysis (3)
src/mocks/WhatsAppForm.tsx (2)
src/graphql/queries/WhatsAppForm.ts (3)
  • LIST_FORM_CATEGORIES (21-25)
  • LIST_WHATSAPP_FORMS (27-39)
  • GET_WHATSAPP_FORM (3-19)
src/graphql/mutations/WhatsAppForm.ts (4)
  • CREATE_FORM (3-15)
  • PUBLISH_FORM (44-56)
  • DEACTIVATE_FORM (58-70)
  • UPDATE_FORM (17-29)
src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.test.tsx (3)
src/mocks/WhatsAppForm.tsx (5)
  • WHATSAPP_FORM_MOCKS (274-283)
  • publishWhatsappForm (69-84)
  • publishWhatsappFormError (103-111)
  • deactivateWhatsappForm (86-102)
  • deactivateWhatsappFormError (113-121)
src/containers/WhatsAppForms/WhatsAppForms.tsx (1)
  • WhatsAppForms (27-215)
src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx (1)
  • WhatsAppFormList (67-259)
src/containers/WhatsAppForms/WhatsAppForms.tsx (3)
src/graphql/queries/WhatsAppForm.ts (2)
  • GET_WHATSAPP_FORM (3-19)
  • LIST_FORM_CATEGORIES (21-25)
src/graphql/mutations/WhatsAppForm.ts (3)
  • CREATE_FORM (3-15)
  • UPDATE_FORM (17-29)
  • DELETE_FORM (31-42)
src/common/HelpData.tsx (1)
  • whatsappFormsInfo (143-146)
🪛 Biome (2.1.2)
src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.test.tsx

[error] 15-16: Do not export from a test file.

(lint/suspicious/noExportsInTest)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: glific (1.18.3-otp-27, 27.3.3)
  • GitHub Check: CI
🔇 Additional comments (2)
src/containers/WhatsAppForms/WhatsAppForm.module.css (1)

1-75: Flow builder styles look consistent and self-contained

The new WhatsApp Flow builder styles are coherent, scoped via CSS modules, and won’t affect behavior. No issues from a code perspective.

src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.module.css (1)

1-151: WhatsApp form list styles are well-structured and scoped

The new list view styles (search bar, status badges, category tags, “more” menu, etc.) are cleanly organized and contained in the CSS module, with no apparent behavioral or maintainability issues.

Comment on lines +28 to +34
const [name, setName] = useState('');
const [description, setDescription] = useState('');
const [formJson, setFormJson] = useState();
const [formCategories, setFormCategories] = useState([]);
const [categories, setCategories] = useState([]);
const [disabled, setDisabled] = useState(false);
const params = useParams();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix formJson state typing and initialization.

The formJson state on line 30 lacks a type annotation and is initialized as undefined. This causes issues:

  1. Type safety: No TypeScript type checking for this critical state.
  2. Line 67 impact: JSON.stringify(undefined) returns the string "undefined", not a valid JSON string, which will cause validation and backend errors.
  3. Line 143-151 validation: The Yup validation expects a string but receives undefined initially.

Apply this diff to fix the typing and initialization:

-  const [formJson, setFormJson] = useState();
+  const [formJson, setFormJson] = useState<any>(null);

And update line 67 to handle the null case:

   const states = {
     name,
-    formJson: JSON.stringify(formJson),
+    formJson: formJson ? JSON.stringify(formJson) : '',
     formCategories,
     description,
   };

Alternatively, for better type safety, define a proper interface for the form JSON structure instead of using any.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +36 to +44
useQuery(GET_WHATSAPP_FORM, {
skip: !params.id,
variables: { id: params.id },
onCompleted: ({ whatsappForm }) => {
if (whatsappForm?.whatsappForm?.status === 'PUBLISHED') {
setDisabled(true);
}
},
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Handle loading and error states for form data query.

The first useQuery hook fetches form data for editing but doesn't extract or handle loading or error states. This can cause issues:

  1. The form may render before data is loaded, showing empty fields briefly.
  2. Users won't see feedback if the query fails.
  3. The setStates function (line 82) is never called with this data, so the form fields won't be populated when editing.

Apply this diff to handle loading/error states and populate the form:

-  useQuery(GET_WHATSAPP_FORM, {
+  const { loading: formLoading } = useQuery(GET_WHATSAPP_FORM, {
     skip: !params.id,
     variables: { id: params.id },
     onCompleted: ({ whatsappForm }) => {
+      const form = whatsappForm?.whatsappForm;
+      if (form) {
+        setStates({
+          name: form.name,
+          definition: form.definition,
+          description: form.description,
+          categories: form.categories,
+        });
+      }
-      if (whatsappForm?.whatsappForm?.status === 'PUBLISHED') {
+      if (form?.status === 'PUBLISHED') {
         setDisabled(true);
       }
     },
   });

Then update the loading check on line 156:

-  if (loading) {
+  if (loading || formLoading) {
     return <Loading />;
   }

Comment on lines +82 to +96
const setStates = ({ name, definition, description, categories }: any) => {
setName(name);
setDescription(description);

setFormCategories(categories.map((c: string) => ({ id: c, name: c })));

let parsedDefinition;
try {
parsedDefinition = JSON.parse(definition);
} catch (e) {
setLogs('Error parsing whatsapp form definition JSON:', 'error');
parsedDefinition = definition;
}
setFormJson(parsedDefinition);
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add type safety and null check for categories.

Two issues:

  1. The function parameter uses any type, losing TypeScript benefits.
  2. Line 86 assumes categories exists and is an array without validation.

Define an interface and add validation:

interface WhatsAppFormBackendData {
  name: string;
  definition: string;
  description: string;
  categories: string[];
}

Apply this diff:

-  const setStates = ({ name, definition, description, categories }: any) => {
+  const setStates = ({ name, definition, description, categories }: WhatsAppFormBackendData) => {
     setName(name);
     setDescription(description);

-    setFormCategories(categories.map((c: string) => ({ id: c, name: c })));
+    if (categories && Array.isArray(categories)) {
+      setFormCategories(categories.map((c: string) => ({ id: c, name: c })));
+    }

     let parsedDefinition;
     try {
       parsedDefinition = JSON.parse(definition);
     } catch (e) {
       setLogs('Error parsing whatsapp form definition JSON:', 'error');
       parsedDefinition = definition;
     }
     setFormJson(parsedDefinition);
   };
🤖 Prompt for AI Agents
In src/containers/WhatsAppForms/WhatsAppForms.tsx around lines 82 to 96, the
setStates parameter is typed as any and categories is used without validation;
define a typed interface (e.g., WhatsAppFormBackendData with name:string,
definition:string, description:string, categories?: string[]) and change the
function signature to accept that type, then validate categories with
Array.isArray(categories) before mapping (otherwise setFormCategories([])); keep
the existing JSON.parse try/catch but ensure types align with the new interface.

* Add WhatsApp Form support with new interface and UI components

* Enhance WhatsApp Form integration by updating button structure and handling in HSM and TemplateOptions components

* Add Gupshup WhatsApp Form constant and update TemplateOptions for structured data collection

* fix: test case

* Add WhatsApp Form support with new interface and UI components

* Enhance WhatsApp Form integration by updating button structure and handling in HSM and TemplateOptions components

* Add Gupshup WhatsApp Form constant and update TemplateOptions for structured data collection

* fix: css

* fix: css

* fix: add test case

* Enhance WhatsApp Form handling by adding validation for form fields and displaying error messages

* fix: update git checkout branch in cypress testing workflow

* added dropdown for screen name

* replaced '!!!' with '!'

* updated cypress branch

* fix: test case

---------

Co-authored-by: priyanshu6238 <[email protected]>
@github-actions github-actions bot temporarily deployed to pull request November 18, 2025 16:30 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/containers/HSM/HSM.tsx (1)

360-375: Remove unused setType prop from TemplateOptions component instantiation

The review comment is verified as accurate. setType is passed to the TemplateOptions component at line 634 in HSM.tsx, but TemplateOptionsProps (lines 32-44 in TemplateOptions.tsx) does not declare this prop, and the component does not consume it. This causes a TypeScript type mismatch and represents unused code.

Remove setType from the component props in HSM.tsx around line 634, as recommended.

♻️ Duplicate comments (1)
src/mocks/WhatsAppForm.tsx (1)

69-102: Fix publish/deactivate mutation mock shapes to match the GraphQL schema

Both publish and deactivate mocks currently return the wrong structure and will not match the PUBLISH_FORM / DEACTIVATE_FORM mutation definitions:

  • publishWhatsappForm should wrap the payload under whatsappForm and include errors.
  • deactivateWhatsappForm is using the wrong field name (publishWhatsappForm), a flat payload, and a lowercase inactive status instead of INACTIVE.

Align them with the schema like this:

 export const publishWhatsappForm = {
   request: {
     query: PUBLISH_FORM,
     variables: {
       id: '3',
     },
   },
   result: {
     data: {
-      publishWhatsappForm: {
-        id: '1',
-        status: 'PUBLISHED',
-      },
+      publishWhatsappForm: {
+        whatsappForm: {
+          id: '1',
+          status: 'PUBLISHED',
+        },
+        errors: null,
+      },
     },
   },
 };
 
 export const deactivateWhatsappForm = {
   request: {
     query: DEACTIVATE_FORM,
     variables: {
       id: '3',
     },
   },
   result: {
     data: {
-      publishWhatsappForm: {
-        id: '1',
-        status: 'inactive',
-        __typename: 'WhatsappForm',
-      },
+      deactivateWhatsappForm: {
+        whatsappForm: {
+          id: '1',
+          status: 'INACTIVE',
+        },
+        errors: null,
+      },
     },
   },
 };
🧹 Nitpick comments (19)
src/mocks/WhatsAppForm.tsx (1)

103-121: Tweak deactivate error mock message for clarity (optional)

For deactivateWhatsappFormError, consider updating the message to something like "Failed to deactivate" so logs and test failures clearly distinguish it from the publish path.

 export const deactivateWhatsappFormError = {
   request: {
     query: DEACTIVATE_FORM,
     variables: {
       id: '3',
     },
   },
-  error: new Error('Failed to publish'),
+  error: new Error('Failed to deactivate'),
 };
src/containers/HSM/HSM.helper.ts (1)

1-88: WhatsApp form button mapping is consistent; consider tightening types

The new WHATSAPP_FORM handling (flow_id → form_id and template string [text, navigate_screen, form_id]) is consistent across getTemplateAndButtons and convertButtonsToTemplate and should work as expected.

You could optionally reduce any usage by wiring WhatsappFormTemplate into the signatures where applicable (e.g., the WHATSAPP_FORM branch of getTemplateAndButtons and convertButtonsToTemplate) to catch shape regressions at compile time.

src/containers/TemplateOptions/TemplateOptions.module.css (1)

1-3: New template option styles integrate cleanly

The added container/wrapper/error classes and the tightened child selectors preserve existing behavior while giving the WhatsApp form template its own structured layout; nothing problematic from a CSS‑modules perspective.

If you find multiple modules defining generic .Errors in future, you might consider a more specific name, but it’s fine as-is here.

Also applies to: 26-27, 31-37, 45-47, 55-56, 67-69, 110-112, 138-155

src/mocks/Template.tsx (1)

236-279: CREATE_SESSION_TEMPLATE_MOCK shape looks good; consider aligning translations type

The mock matches the CREATE_TEMPLATE mutation structure and correctly returns a WHATSAPP_FORM / FLOW button payload with buttonType: 'WHATSAPP_FORM', which should exercise the new flow well. The only nit is translations: [] — other mocks in this file tend to use a JSON string (e.g. '{}') or serialized object, so you may want to align this for consistency with how the field is usually shaped in tests.

src/containers/TemplateOptions/TemplateOptions.test.tsx (2)

18-30: Tests rely heavily on positional queries; prefer more specific selectors

Both tests use getAllByRole('textbox') / getAllByRole('radio') and index into the arrays to find controls. This is brittle against layout or field‑order changes. It would be more robust to:

  • Target radios by label text (e.g., role radio with name /Phone number/).
  • Target textboxes by name, placeholder, or aria-label instead of by index.
    Also, await waitFor(() => {}); is effectively a no‑op; either assert a condition inside waitFor or remove it.

Also applies to: 32-57


59-77: “quick reply button” test doesn’t exercise Quick Reply path

This test selects “Call to Action” in the button‑type dropdown but is named “renders quick reply button template”. It never selects the “Quick Reply” option or asserts quick‑reply‑specific behavior, so either:

  • Rename the test to reflect the Call to Action path, or
  • Change the selection to “Quick Reply” and assert the quick‑reply UI/behavior.
src/containers/HSM/HSM.test.tsx (3)

197-268: WhatsApp Form creation test is thorough but duplicates earlier test flow

The WhatsApp Form test is comprehensive and closely mirrors the basic “create template message” test (same setup, text entry, category selection, variable/ footer handling). Consider extracting a small helper that performs the shared setup (up to “Add buttons”) so this test only covers the WhatsApp‑specific combobox interactions and assertions.


81-89: Avoid combobox access by hard‑coded indices

Multiple tests retrieve comboboxes and other inputs via getAllByRole('combobox')[N] or similar indexing. This is fragile as any UI change in field ordering will break these tests. Prefer:

  • getByLabelText('Select Button Type') for the button‑type dropdown,
  • Other getByLabelText/findByLabelText or data-testid selectors for subsequent selects,
    so the tests depend on semantics rather than DOM order.

Also applies to: 169-173, 297-300, 351-355, 419-431, 476-483


468-496: userEvent usage inside waitFor may be flaky

In the “should not allow adding more than 10 quick reply buttons” test, user.click(addButton!) is called inside waitFor without await, and repeated in a loop. This mixes userEvent’s async behavior with waitFor polling and can introduce flakiness.
Consider simplifying to something like:

for (let i = 0; i < 9; i += 1) {
  const addButton = await screen.findByText('Add Quick Reply');
  await user.click(addButton);
}

and then assert the absence of the button.

src/containers/TemplateOptions/TemplateOptions.tsx (2)

79-97: LIST_WHATSAPP_FORMS query: consider minimal error/null‑safety handling

The useQuery(LIST_WHATSAPP_FORMS, { onCompleted }) block correctly maps forms to { label, id, definition }, but it assumes data.listWhatsappForms is always an array. If the backend ever returns null or an empty value, data.listWhatsappForms.map will throw.

A small guard, e.g. const list = data?.listWhatsappForms ?? []; setForms(list.map(...)), would make this more resilient without much extra code.


386-425: Header Autocomplete + tooltip wiring looks correct overall

The new “Select Button Type” Autocomplete and tooltip correctly bind to buttonOptions and use getInfo(templateType?.id) to show contextual help for CALL_TO_ACTION, QUICK_REPLY, and WHATSAPP_FORM. Given disableClearable is set, templateType should always be one of the options, so the tooltip text will stay consistent with the selected button type.

src/containers/HSM/HSM.tsx (8)

57-67: buttonTypes and buttonOptions correctly extended for WhatsApp Form

Adding WHATSAPP_FORM to buttonTypes and exporting buttonOptions with { id, label } objects aligns well with the new TemplateOptions UI and with the WhatsappFormTemplate shape (form_id, text, navigate_screen). This keeps button initialization and selection consistent across the HSM form.


82-85: templateButtons and templateType state changes are coherent

Widening templateButtons to CallToActionTemplate | QuickReplyTemplate | WhatsappFormTemplate and storing templateType as a full option object (buttonOptions[0]) is a good direction and works with the templateType?.id checks used elsewhere (payload, validation, simulator). This keeps the type/source of button templates centralized and consistent.

Also applies to: 92-96


238-283: WHATSAPP_FORM payload generation in getButtonTemplatePayload looks correct

The new branch:

if (templateType?.id === 'WHATSAPP_FORM') {
  const obj = { type: 'FLOW', navigate_screen, text, flow_id: form_id, flow_action: 'NAVIGATE' };
  result.push(obj);
}

matches what the mock (CREATE_SESSION_TEMPLATE_MOCK) returns and what the backend is likely expecting for WhatsApp Form buttons (FLOW type with flow_id, navigate_screen, and text). Reusing buttonType: templateType?.id keeps the payload coherent with other button types.


333-345: setStates correctly maps persisted buttonType to buttonOptions entry

When templates have hasButtons, setStates now calls:

setTemplateType(buttonOptions.find((btn: any) => btn.id === templateButtonType));

This properly rehydrates the templateType object for CALL_TO_ACTION, QUICK_REPLY, or WHATSAPP_FORM so the UI and validation operate on the right branch. You might optionally guard with a fallback for unknown types, but the current behavior is fine if only these three values are ever stored.


421-429: addTemplateButtons correctly uses templateType.id but depends on templateType being set

addTemplateButtons now uses buttonTypes[templateType?.id], which aligns with the new buttonOptions structure. This works well with handleTemplateTypeChange and the useEffect that seeds default buttons when templateType changes.

Just ensure templateType is always one of the known options before calling addTemplateButtons; the current guards (if (templateType?.id)) are sufficient as long as templateType is never set to an arbitrary object.


457-479: Template button input handler change is consistent with new TemplateOptions contract

handeInputChange now takes a value instead of an event object, and TemplateOptions calls it with e.target.value. The logic resetting the row for eventType === 'type' and otherwise mutating obj[eventType] fits all three button types (CALL_TO_ACTION fields, QUICK_REPLY value, and WHATSAPP_FORM form_id/text/navigate_screen). This keeps templateButtons updates centralized.


793-812: Yup validation correctly extended for WHATSAPP_FORM buttons

The lazy schema now includes:

else if (templateType?.id === 'WHATSAPP_FORM') {
  return Yup.object().shape({
    form_id: Yup.string().required('Form is required.'),
    text: Yup.string().required('Button title is required.'),
    navigate_screen: Yup.string().required('Screen is required.'),
  });
}

This matches the WhatsApp Form template shape and ensures incomplete button definitions are blocked before submission. The use of templateType?.id is consistent with the rest of the component.


845-849: Simulator message updates correctly consider new templateType shape

The effects that:

  • add default buttons when templateType changes, and
  • convert templateButtons to text via convertButtonsToTemplate(templateButtons, templateType?.id)

are coherent with the new object‑shaped templateType and extended convertButtonsToTemplate helper. This keeps preview text in sync with CALL_TO_ACTION, QUICK_REPLY, and WHATSAPP_FORM buttons.

Also applies to: 861-865

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b91823 and c2a8b06.

📒 Files selected for processing (10)
  • src/common/RichEditor.tsx (1 hunks)
  • src/common/constants.ts (1 hunks)
  • src/containers/HSM/HSM.helper.ts (4 hunks)
  • src/containers/HSM/HSM.test.tsx (8 hunks)
  • src/containers/HSM/HSM.tsx (15 hunks)
  • src/containers/TemplateOptions/TemplateOptions.module.css (7 hunks)
  • src/containers/TemplateOptions/TemplateOptions.test.tsx (2 hunks)
  • src/containers/TemplateOptions/TemplateOptions.tsx (12 hunks)
  • src/mocks/Template.tsx (1 hunks)
  • src/mocks/WhatsAppForm.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

Files:

  • src/common/constants.ts
  • src/common/RichEditor.tsx
  • src/containers/HSM/HSM.helper.ts
  • src/mocks/Template.tsx
  • src/containers/HSM/HSM.test.tsx
  • src/containers/TemplateOptions/TemplateOptions.tsx
  • src/containers/HSM/HSM.tsx
  • src/containers/TemplateOptions/TemplateOptions.test.tsx
  • src/mocks/WhatsAppForm.tsx
🧬 Code graph analysis (7)
src/containers/HSM/HSM.helper.ts (1)
src/common/constants.ts (1)
  • WHATSAPP_FORM (183-183)
src/mocks/Template.tsx (1)
src/graphql/mutations/Template.ts (1)
  • CREATE_TEMPLATE (14-47)
src/containers/HSM/HSM.test.tsx (2)
src/mocks/WhatsAppForm.tsx (1)
  • WHATSAPP_FORM_MOCKS (298-308)
src/mocks/Template.tsx (1)
  • CREATE_SESSION_TEMPLATE_MOCK (236-279)
src/containers/TemplateOptions/TemplateOptions.tsx (3)
src/common/constants.ts (6)
  • CALL_TO_ACTION (180-180)
  • GUPSHUP_CALL_TO_ACTION (170-171)
  • QUICK_REPLY (182-182)
  • GUPSHUP_QUICK_REPLY (174-175)
  • WHATSAPP_FORM (183-183)
  • GUPSHUP_WHATSAPP_FORM (177-177)
src/graphql/queries/WhatsAppForm.ts (1)
  • LIST_WHATSAPP_FORMS (27-39)
src/containers/HSM/HSM.tsx (1)
  • buttonOptions (63-67)
src/containers/HSM/HSM.tsx (3)
src/containers/HSM/HSM.helper.ts (4)
  • CallToActionTemplate (3-7)
  • QuickReplyTemplate (9-11)
  • WhatsappFormTemplate (13-17)
  • convertButtonsToTemplate (37-50)
src/containers/InteractiveMessage/InteractiveOptions/QuickReplyTemplate.tsx (1)
  • QuickReplyTemplate (17-78)
src/common/constants.ts (2)
  • CALL_TO_ACTION (180-180)
  • QUICK_REPLY (182-182)
src/containers/TemplateOptions/TemplateOptions.test.tsx (2)
src/mocks/WhatsAppForm.tsx (1)
  • WHATSAPP_FORM_MOCKS (298-308)
src/containers/HSM/HSM.tsx (1)
  • HSM (69-919)
src/mocks/WhatsAppForm.tsx (2)
src/graphql/queries/WhatsAppForm.ts (3)
  • LIST_FORM_CATEGORIES (21-25)
  • LIST_WHATSAPP_FORMS (27-39)
  • GET_WHATSAPP_FORM (3-19)
src/graphql/mutations/WhatsAppForm.ts (4)
  • CREATE_FORM (3-15)
  • PUBLISH_FORM (44-56)
  • DEACTIVATE_FORM (58-70)
  • UPDATE_FORM (17-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: glific (1.18.3-otp-27, 27.3.3)
  • GitHub Check: build
  • GitHub Check: CI
🔇 Additional comments (4)
src/common/RichEditor.tsx (1)

137-155: Icon selection for call-to-action buttons looks good

The added digit check to render CallIcon for phone-like values cleanly complements the existing link handling and keeps the behavior explicit without introducing regressions.

src/common/constants.ts (1)

177-184: WhatsApp form constants are consistent and well-placed

GUPSHUP_WHATSAPP_FORM and WHATSAPP_FORM align with existing naming and are positioned correctly next to other template-type constants.

src/containers/TemplateOptions/TemplateOptions.test.tsx (1)

1-16: Ensure HSM has all required GraphQL mocks in this wrapper

The wrapper only injects WHATSAPP_FORM_MOCKS into MockedProvider, but HSM also fires template, tags, languages, and categories queries. Please double‑check that WHATSAPP_FORM_MOCKS (or upstream defaults) cover all of those; otherwise these tests may intermittently error with missing mock warnings.

src/containers/HSM/HSM.test.tsx (1)

94-101: Good consolidation of mocks for add mode

Merging HSM_TEMPLATE_MOCKS, WHATSAPP_FORM_MOCKS, and CREATE_SESSION_TEMPLATE_MOCK into a single MOCKS array is a clean way to cover all GraphQL interactions for add mode, including WhatsApp forms and template creation.

Comment on lines +18 to 31
import {
GUPSHUP_CALL_TO_ACTION,
GUPSHUP_QUICK_REPLY,
CALL_TO_ACTION,
QUICK_REPLY,
WHATSAPP_FORM,
GUPSHUP_WHATSAPP_FORM,
} from 'common/constants';
import styles from './TemplateOptions.module.css';
import { Fragment } from 'react';
import { Fragment, useState } from 'react';
import { buttonOptions } from 'containers/HSM/HSM';
import { useQuery } from '@apollo/client';
import { LIST_WHATSAPP_FORMS } from 'graphql/queries/WhatsAppForm';

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Avoid circular dependency between HSM and TemplateOptions via buttonOptions

TemplateOptions imports buttonOptions from containers/HSM/HSM, while HSM imports TemplateOptions. This creates a circular module dependency which can lead to temporal‑dead‑zone issues and makes the module graph harder to reason about.

Consider moving buttonOptions (and the associated type) into a small shared module (e.g., containers/HSM/buttonOptions.ts or a constants file) and importing it from both HSM and TemplateOptions instead.



🏁 Script executed:

#!/bin/bash
# Verify circular dependency: search for buttonOptions import in TemplateOptions
echo "=== Searching for buttonOptions import in TemplateOptions.tsx ==="
rg -n "buttonOptions" "src/containers/TemplateOptions/TemplateOptions.tsx" -A2 -B2

echo ""
echo "=== Searching for all imports from HSM in TemplateOptions ==="
rg -n "from.*HSM" "src/containers/TemplateOptions/TemplateOptions.tsx" -A2 -B2

echo ""
echo "=== Searching for TemplateOptions import in HSM file ==="
rg -n "TemplateOptions" "src/containers/HSM/HSM.tsx" -A2 -B2
rg -n "TemplateOptions" "src/containers/HSM/HSM.ts" -A2 -B2

echo ""
echo "=== Finding HSM file location ==="
fd -t f "HSM\." "src/containers/HSM/"

echo ""
echo "=== Checking buttonOptions definition ==="
rg -n "buttonOptions\s*=" "src/containers/HSM/" -B5 -A5

Length of output: 1743



🏁 Script executed:

#!/bin/bash
# Search for buttonOptions more broadly
echo "=== Search for buttonOptions definition across codebase ==="
rg -n "export.*buttonOptions|buttonOptions\s*=" "src/" -B3 -A3

echo ""
echo "=== Check HSM.tsx exports around line 28 and before TemplateOptions import ==="
rg -n "export" "src/containers/HSM/HSM.tsx" -B2 -A2 | head -50

echo ""
echo "=== Check import structure of HSM.tsx ==="
head -100 "src/containers/HSM/HSM.tsx"

Length of output: 5562


Move buttonOptions to a shared module to break circular dependency

Circular dependency confirmed: TemplateOptions imports buttonOptions from containers/HSM/HSM, while HSM imports TemplateOptions (line 21). This creates a module cycle that can lead to initialization issues and makes the dependency graph fragile.

buttonOptions (defined at HSM.tsx line 63) is a simple constant array and suitable for extraction. Move it to a shared module such as containers/HSM/buttonOptions.ts or a constants file, then import it in both files to cleanly resolve the circular dependency.

🤖 Prompt for AI Agents
In src/containers/TemplateOptions/TemplateOptions.tsx around lines 18 to 31,
TemplateOptions currently imports buttonOptions from containers/HSM/HSM which
creates a circular dependency because HSM imports TemplateOptions; extract the
buttonOptions constant (defined in HSM at line ~63) into a new shared module
(e.g., src/containers/HSM/buttonOptions.ts or a common constants file), export
it from there, then update both HSM and TemplateOptions to import buttonOptions
from the new module to break the circular import.

Comment on lines +321 to +382
if (templateType?.id === WHATSAPP_FORM) {
template = (
<div className={styles.WhatsappFormTemplateWrapper}>
<div>
<Autocomplete
options={forms}
value={forms.find((form: any) => form.id === form_id) || null}
renderInput={(params) => <TextField {...params} label="Select Form " />}
onChange={(event: any, newValue: any) => {
onInputChange(newValue.id, row, index, 'form_id');

try {
const definition = JSON.parse(newValue.definition);
const screenNames = definition.screens.map((screen: any) => screen.id);
setScreens(screenNames.map((screen: string) => ({ label: screen, id: screen })));
} catch (e) {
setScreens([]);
console.error('Error parsing form definition:', e);
}
}}
disabled={disabled}
/>
{errors.templateButtons && touched.templateButtons && touched.templateButtons[index] ? (
<p className={styles.Errors}>{errors.templateButtons[index]?.form_id}</p>
) : null}
</div>

<div>
<Autocomplete
options={screens}
value={navigate_screen}
renderInput={(params) => <TextField {...params} label="Screen Name" />}
onChange={(event: any, newValue: any) => {
console.log(newValue);
onInputChange(newValue.id, row, index, 'navigate_screen');
}}
disabled={disabled || !form_id}
/>

{errors.templateButtons && touched.templateButtons && touched.templateButtons[index] ? (
<p className={styles.Errors}>{errors.templateButtons[index]?.navigate_screen}</p>
) : null}
</div>

<div>
<TextField
value={text}
title={title}
placeholder={`Button Title`}
variant="outlined"
onChange={(e: any) => onInputChange(e.target.value, row, index, 'text')}
className={styles.TextField}
error={isError('value')}
disabled={disabled}
/>
{errors.templateButtons && touched.templateButtons && touched.templateButtons[index] ? (
<p className={styles.Errors}>{errors.templateButtons[index]?.text}</p>
) : null}
</div>
</div>
);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

WhatsApp Form Autocomplete block has null‑handling and value‑type issues

In the WHATSAPP_FORM branch:

  • onChange={(event, newValue) => { onInputChange(newValue.id, ...) ... }} assumes newValue is always non‑null. If the user clears the selection, this will throw.
  • The screens Autocomplete uses options={screens} but value={navigate_screen}, which is a string. MUI Autocomplete expects the value to be either one of the option objects or null; this can produce inconsistent UI and warnings.
  • The Button Title TextField uses error={isError('value')} while the actual error message is errors.templateButtons[index]?.text, so the red error state may not match validation errors on text.

Suggested adjustments:

// Form selection
onChange={(event: any, newValue: any) => {
  if (!newValue) {
    onInputChange('', row, index, 'form_id');
    setScreens([]);
    return;
  }
  onInputChange(newValue.id, row, index, 'form_id');
  try {
    const definition = JSON.parse(newValue.definition);
    const screenNames = definition.screens.map((screen: any) => screen.id);
    setScreens(screenNames.map((screen: string) => ({ label: screen, id: screen })));
  } catch {
    setScreens([]);
  }
}}

// Screens Autocomplete
<Autocomplete
  options={screens}
  value={screens.find((s: any) => s.id === navigate_screen) || null}
  ...
  onChange={(event: any, newValue: any) => {
    onInputChange(newValue ? newValue.id : '', row, index, 'navigate_screen');
  }}
/>

// Button title error flag
<TextField
  ...
  error={isError('text')}
/>

This keeps the stored form state as IDs while satisfying the Autocomplete’s expectations and aligns the error prop with the validated field.



---

🏁 Script executed:

```shell
#!/bin/bash
# Inspect the component file to understand state management and function definitions
cat src/containers/TemplateOptions/TemplateOptions.tsx | head -400 | tail -200

Length of output: 8176


🏁 Script executed:

#!/bin/bash
# Search for onInputChange function definition
rg -n "onInputChange" src/containers/TemplateOptions/TemplateOptions.tsx -B3 -A8

Length of output: 5083


🏁 Script executed:

#!/bin/bash
# Search for isError function definition
rg -n "isError" src/containers/TemplateOptions/TemplateOptions.tsx -B3 -A5

Length of output: 4437


🏁 Script executed:

#!/bin/bash
# Search for state declarations (form_id, navigate_screen, screens)
rg -n "form_id|navigate_screen|setScreens|useState" src/containers/TemplateOptions/TemplateOptions.tsx -B2 -A2

Length of output: 2530


🏁 Script executed:

#!/bin/bash
# Get the full component structure and hooks at the top
head -100 src/containers/TemplateOptions/TemplateOptions.tsx

Length of output: 2677


Null-handling and type mismatches confirmed in WhatsApp Form section—fixes required

All three concerns are legitimate:

  1. Line 330 null crash: onChange accesses newValue.id without null check. Clearing the form selection will throw.
  2. Line 351 type mismatch: value={navigate_screen} is a string, but options={screens} contains objects { label, id }. MUI Autocomplete requires value to match option type.
  3. Line 373 error flag mismatch: Uses error={isError('value')} but the field is for text and the actual validation error is errors.templateButtons[index]?.text (line 377).

Also line 355 accesses newValue.id without null checking in the screens Autocomplete onChange.

// Form selection—add null guard
onChange={(event: any, newValue: any) => {
  if (!newValue) {
    onInputChange('', row, index, 'form_id');
    setScreens([]);
    return;
  }
  onInputChange(newValue.id, row, index, 'form_id');
  try {
    const definition = JSON.parse(newValue.definition);
    const screenNames = definition.screens.map((screen: any) => screen.id);
    setScreens(screenNames.map((screen: string) => ({ label: screen, id: screen })));
  } catch (e) {
    setScreens([]);
    console.error('Error parsing form definition:', e);
  }
}}

// Screens—match value type to options and add null guard
value={screens.find((s: any) => s.id === navigate_screen) || null}
onChange={(event: any, newValue: any) => {
  onInputChange(newValue ? newValue.id : '', row, index, 'navigate_screen');
}}

// Button title—fix error prop
error={isError('text')}
🤖 Prompt for AI Agents
In src/containers/TemplateOptions/TemplateOptions.tsx around lines 321-382, the
WhatsApp form block can crash or misbehave: guard against null newValue in the
form Autocomplete onChange (when selection is cleared) by setting form_id to ''
and clearing screens; parse definition only when newValue is present; for the
screens Autocomplete make value match option type by using the object from
screens (find by id) or null and guard its onChange to handle newValue === null
(set navigate_screen to ''); and fix the TextField error prop to call
isError('text') so it reflects the text validation error.

@github-actions github-actions bot temporarily deployed to pull request November 21, 2025 09:51 Inactive
@github-actions github-actions bot temporarily deployed to pull request November 24, 2025 05:04 Inactive
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.

4 participants