@@ -249,7 +292,7 @@ export const TemplateOptions = ({
title={title}
placeholder={`Quick reply ${index + 1} title`}
variant="outlined"
- onChange={(e: any) => onInputChange(e, row, index, 'value')}
+ onChange={(e: any) => onInputChange(e.target.value, row, index, 'value')}
className={styles.TextField}
error={isError('value')}
slotProps={{
@@ -274,58 +317,111 @@ export const TemplateOptions = ({
>
);
}
+
+ if (templateType?.id === WHATSAPP_FORM) {
+ template = (
+
+ );
+ }
return template;
};
- const radioTemplateType = (
-
-
onTemplateTypeChange(event.target.value)}
- >
-
- }
- label="Call to actions"
- classes={{ root: styles.RadioLabel }}
- />
-
-
-
-
-
- }
- label="Quick replies"
- className={styles.RadioLabel}
- />
-
-
-
-
-
+ return (
+ <>
+ {isAddButtonChecked && (
+
+
+
}
+ value={templateType}
+ onChange={(event: any, newValue: any) => {
+ onTemplateTypeChange(newValue);
+ }}
+ fullWidth
+ disabled={disabled}
+ disableClearable
+ />
- {templateType ? (
-
-
(
-
- {inputFields.map((row: any, index: any) => (
-
{getButtons(row, index, arrayHelpers)}
- ))}
-
- )}
- />
+
+
+
+
+
+ {templateType ? (
+
+
(
+
+ {inputFields.map((row: any, index: any) => (
+
{getButtons(row, index, arrayHelpers)}
+ ))}
+
+ )}
+ />
+
+ ) : null}
- ) : null}
-
+ )}
+ >
);
-
- return
{isAddButtonChecked && radioTemplateType}
;
};
diff --git a/src/containers/WhatsAppForms/WhatsAppForm.module.css b/src/containers/WhatsAppForms/WhatsAppForm.module.css
new file mode 100644
index 0000000000..c4335f42df
--- /dev/null
+++ b/src/containers/WhatsAppForms/WhatsAppForm.module.css
@@ -0,0 +1,75 @@
+.FlowBuilderInfo {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 1.5rem;
+ margin: 2rem;
+ margin-bottom: 0;
+ background: linear-gradient(135deg, #f0fdf4 0%, #ecfdf5 100%);
+ border: 1px solid #bbf7d0;
+ border-radius: 12px;
+ box-shadow: 0 1px 3px 0 #22c55e1a;
+ transition: all 0.2s ease-in-out;
+}
+
+.FlowBuilderInfo:hover {
+ box-shadow: 0 4px 6px -1px #22c55e26;
+ transform: translateY(-1px);
+}
+
+.FlowBuilderInfo p {
+ margin-bottom: 0;
+}
+
+.InfoContent {
+ display: flex;
+ align-items: flex-start;
+ gap: 1rem;
+ flex: 1;
+}
+
+.IconWrapper {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 3rem;
+ height: 3rem;
+ background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
+ border-radius: 12px;
+ flex-shrink: 0;
+}
+
+.Icon {
+ color: white !important;
+ font-size: 24px !important;
+}
+
+.Title {
+ margin: 0 0 8px;
+ font-size: 1.125rem;
+ font-weight: 600;
+ color: #14532d;
+ line-height: 1.4;
+}
+
+.Description {
+ margin: 0;
+ font-size: 0.875rem;
+ color: #16a34a;
+ line-height: 1.5;
+}
+
+.FlowBuilderButton {
+ padding: 0.75rem 1.5rem !important;
+ font-weight: 500 !important;
+ border-radius: 8px !important;
+ white-space: nowrap;
+ min-width: 160px;
+ transition: all 0.2s ease-in-out !important;
+ color: #fff !important;
+}
+
+.FlowBuilderButton:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 4px 12px #22c55e4d !important;
+}
diff --git a/src/containers/WhatsAppForms/WhatsAppForm.test.tsx b/src/containers/WhatsAppForms/WhatsAppForm.test.tsx
new file mode 100644
index 0000000000..f8fd25d3b7
--- /dev/null
+++ b/src/containers/WhatsAppForms/WhatsAppForm.test.tsx
@@ -0,0 +1,86 @@
+import { MockedProvider } from '@apollo/client/testing';
+import { fireEvent, render, waitFor } from '@testing-library/react';
+import * as Notification from 'common/notification';
+import { formJson, WHATSAPP_FORM_MOCKS } from 'mocks/WhatsAppForm';
+import { MemoryRouter, Route, Routes } from 'react-router';
+import WhatsAppFormList from './WhatsAppFormList/WhatsAppFormList';
+import WhatsAppForms from './WhatsAppForms';
+
+describe('
', () => {
+ const notificationSpy = vi.spyOn(Notification, 'setNotification');
+ const wrapper = (initialEntry: string = '/whatsapp-forms/add') => (
+
+
+
+ } />
+ } />
+ } />
+
+
+
+ );
+
+ test('it should render the WhatsApp Form page initially', async () => {
+ const { getByText } = render(wrapper());
+ expect(getByText('Loading...')).toBeInTheDocument();
+
+ await waitFor(() => {
+ expect(getByText('Create WhatsApp Form')).toBeInTheDocument();
+ });
+ });
+
+ test('it should create WhatsApp Form page with form fields', async () => {
+ const { getByTestId, getByText, getAllByRole } = render(wrapper());
+ expect(getByText('Loading...')).toBeInTheDocument();
+
+ await waitFor(() => {
+ expect(getByText('Create WhatsApp Form')).toBeInTheDocument();
+ });
+
+ const inputs = getAllByRole('textbox');
+
+ fireEvent.change(inputs[0], { target: { value: 'Test Form' } });
+ fireEvent.change(inputs[1], { target: { value: 'This is a test form' } });
+ fireEvent.change(inputs[2], { target: { value: 'sign_up' } });
+
+ fireEvent.click(getByTestId('submitActionButton'));
+
+ await waitFor(() => {
+ expect(getByText('Must be valid JSON')).toBeInTheDocument();
+ });
+
+ const autocomplete = getByTestId('AutocompleteInput');
+
+ autocomplete.focus();
+ fireEvent.keyDown(autocomplete, { key: 'ArrowDown' });
+
+ fireEvent.click(getByText('Other'), { key: 'Enter' });
+ fireEvent.change(inputs[2], { target: { value: JSON.stringify(formJson) } });
+
+ fireEvent.click(getByTestId('submitActionButton'));
+
+ await waitFor(() => {
+ expect(notificationSpy).toHaveBeenCalledWith('Whatsapp Form created successfully!');
+ });
+ });
+
+ test('it should edit WhatsApp Form page with form fields', async () => {
+ const { getByTestId, getByText, getAllByRole } = render(wrapper('/whatsapp-forms/1/edit'));
+ expect(getByText('Loading...')).toBeInTheDocument();
+
+ await waitFor(() => {
+ expect(getByText('Edit WhatsApp Form')).toBeInTheDocument();
+ });
+
+ const inputs = getAllByRole('textbox');
+
+ fireEvent.change(inputs[0], { target: { value: 'Updated Form Name' } });
+ fireEvent.change(inputs[1], { target: { value: 'This is an updated test form' } });
+
+ fireEvent.click(getByTestId('submitActionButton'));
+
+ await waitFor(() => {
+ expect(notificationSpy).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.module.css b/src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.module.css
new file mode 100644
index 0000000000..ca826725a6
--- /dev/null
+++ b/src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.module.css
@@ -0,0 +1,151 @@
+.SearchBar {
+ border-radius: 24px;
+ border: 1px solid #ccc;
+ display: flex;
+ margin-right: 8px;
+ height: 36px !important;
+ background: #fff;
+ min-height: 36px !important;
+}
+
+.SearchBar>fieldset {
+ border: none !important;
+}
+
+.Name {
+ width: 27%;
+ min-width: 200px;
+}
+
+.Label {
+ width: 15%;
+}
+
+.Actions {
+ width: 15%;
+ min-width: 200px;
+ text-align: end;
+}
+
+.NameText {
+ line-height: 20px;
+ margin: 0;
+ font-size: 17px !important;
+ word-break: break-all;
+ color: #191c1a !important;
+ font-weight: 500;
+}
+
+.Status {
+ display: inline-block;
+ padding: 4px 12px;
+ border-radius: 6px;
+ font-size: 12px;
+ font-weight: 600;
+ text-align: center;
+}
+
+.PublishBadge {
+ font-size: 15px;
+ composes: Status;
+ background-color: #e8f5e9;
+ color: #2e7d32;
+}
+
+.DraftBadge {
+ font-size: 15px;
+ composes: Status;
+ background-color: #fff3cd;
+ color: #856404;
+}
+
+.InactiveBadge {
+ composes: Status;
+ font-size: 15px;
+ background-color: #f0f0f0;
+ color: #6c757d;
+}
+
+.LabelButton {
+ width: fit-content;
+ min-width: 80px;
+ margin-right: 50px;
+ padding: 6px 12px;
+ color: #555;
+ font-weight: 500;
+ font-size: 15px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-left: -20px;
+ border-radius: 16px;
+ overflow: visible;
+ max-width: 220px;
+}
+
+.CategoryTag {
+ background-color: #fff;
+ border: 1px solid #c4c4c4;
+ border-radius: 12px;
+ padding: 4px 10px;
+ font-size: 14px;
+ font-weight: 500;
+ color: #333;
+ margin-right: 6px;
+ margin-bottom: 4px;
+ display: inline-block;
+}
+
+.CategoryMore {
+ cursor: pointer;
+ color: #1f9075;
+ white-space: nowrap;
+ font-size: 12px;
+ margin-left: 4px;
+ z-index: 10;
+}
+
+.LabelWrapper {
+ position: relative;
+}
+
+.MoreWrapper {
+ position: relative;
+ display: inline-block;
+}
+
+.MoreList {
+ display: none;
+ position: absolute;
+ top: 22px;
+ left: 0;
+ background: white;
+ border: 1px solid #ddd;
+ border-radius: 8px;
+ box-shadow: 0 4px 10px #0000001a;
+ padding: 6px;
+ z-index: 20;
+ min-width: 150px;
+}
+
+.MoreListItem {
+ padding: 5px 10px;
+ font-size: 13px;
+ color: #333;
+ background: #e4e7e4;
+ border-radius: 6px;
+ margin: 2px 0;
+ border: 1px solid #eee;
+}
+
+.MoreListItem:hover {
+ background: #f7f7f7;
+}
+
+.MoreWrapper:hover .MoreList {
+ display: block;
+}
+
+.DialogText {
+ text-align: center;
+}
diff --git a/src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.test.tsx b/src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.test.tsx
new file mode 100644
index 0000000000..d965606b23
--- /dev/null
+++ b/src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.test.tsx
@@ -0,0 +1,214 @@
+import { render, fireEvent, waitFor } from '@testing-library/react';
+import { MemoryRouter, Route, Routes } from 'react-router';
+import { vi } from 'vitest';
+import {
+ publishWhatsappForm,
+ publishWhatsappFormError,
+ WHATSAPP_FORM_MOCKS,
+ deactivateWhatsappForm,
+ deactivateWhatsappFormError,
+} from 'mocks/WhatsAppForm';
+import { MockedProvider } from '@apollo/client/testing';
+import WhatsAppForms from '../WhatsAppForms';
+import * as Notification from 'common/notification';
+import { WhatsAppFormList } from './WhatsAppFormList';
+
+export { publishWhatsappForm, publishWhatsappFormError } from 'mocks/WhatsAppForm';
+
+const mockNavigate = vi.fn();
+
+vi.mock('react-router', async () => {
+ const actual = await vi.importActual
('react-router');
+ return {
+ ...actual,
+ useNavigate: () => mockNavigate,
+ };
+});
+
+vi.mock('common/notification', async (importOriginal) => {
+ const mod = await importOriginal();
+ return {
+ ...mod,
+ setNotification: vi.fn(),
+ setErrorMessage: vi.fn(),
+ };
+});
+
+const wrapper = (extraMocks: any[] = [], initialEntry: string = '/whatsapp-forms') => {
+ const allMocks = [...WHATSAPP_FORM_MOCKS, ...extraMocks];
+ return (
+
+
+
+ } />
+ } />
+ } />
+
+
+
+ );
+};
+
+describe('', () => {
+ test('updates filter value correctly when different options are selected', async () => {
+ const { getByText, getAllByRole, findByText } = render(wrapper());
+ const select = getAllByRole('combobox')[0];
+ fireEvent.click(getByText('All'));
+
+ expect(select).toHaveTextContent('All');
+ fireEvent.mouseDown(select);
+
+ const publishedOption = await findByText('Published');
+ fireEvent.click(publishedOption);
+ expect(select).toHaveTextContent('Published');
+
+ fireEvent.mouseDown(select);
+
+ const inactiveOption = getByText('Inactive');
+ fireEvent.click(inactiveOption);
+ expect(select).toHaveTextContent('Inactive');
+
+ fireEvent.mouseDown(select);
+
+ const draftOption = getByText('Draft');
+ fireEvent.click(draftOption);
+ expect(select).toHaveTextContent('Draft');
+ });
+
+ test('navigates to add form page when "Create New Form" button clicked', () => {
+ const { getByTestId } = render(wrapper());
+
+ const button = getByTestId('newItemButton');
+ fireEvent.click(button);
+
+ expect(mockNavigate).toHaveBeenCalledWith('/whatsapp-forms/add');
+ });
+
+ test('render search bar correctly', () => {
+ const { getByTestId } = render(wrapper());
+ const search = getByTestId('searchForm');
+ expect(search).toBeInTheDocument();
+ });
+
+ test('publishes a form successfully when publish button clicked', async () => {
+ const { getByText, getAllByRole, getByTestId } = render(wrapper([publishWhatsappForm]));
+ const notificationSpy = vi.spyOn(Notification, 'setNotification');
+
+ const select = getAllByRole('combobox')[0];
+ fireEvent.click(getByText('All'));
+
+ expect(select).toHaveTextContent('All');
+ fireEvent.mouseDown(select);
+ const draftOption = getByText('Draft');
+ fireEvent.click(draftOption);
+ expect(select).toHaveTextContent('Draft');
+
+ const publishIcon = await waitFor(() => getByTestId('publish-icon'));
+ fireEvent.click(publishIcon);
+
+ await waitFor(() => {
+ expect(getByTestId('dialogTitle')).toBeInTheDocument();
+ });
+
+ expect(getByTestId('dialogTitle')).toHaveTextContent('Do you want to publish this form');
+
+ const ConfirmButton = await waitFor(() => getByTestId('ok-button'));
+ fireEvent.click(ConfirmButton);
+ await waitFor(() => {
+ expect(notificationSpy).toHaveBeenCalled();
+ });
+ });
+
+ test('shows error message when publish API fails', async () => {
+ const { getByText, getAllByRole, getByTestId } = render(wrapper([publishWhatsappFormError]));
+ const errorSpy = vi.spyOn(Notification, 'setErrorMessage');
+
+ const select = getAllByRole('combobox')[0];
+ fireEvent.click(getByText('All'));
+
+ expect(select).toHaveTextContent('All');
+ fireEvent.mouseDown(select);
+ const draftOption = getByText('Draft');
+ fireEvent.click(draftOption);
+ expect(select).toHaveTextContent('Draft');
+
+ const publishIcon = await waitFor(() => getByTestId('publish-icon'));
+ fireEvent.click(publishIcon);
+
+ await waitFor(() => {
+ expect(getByTestId('dialogTitle')).toBeInTheDocument();
+ });
+
+ expect(getByTestId('dialogTitle')).toHaveTextContent('Do you want to publish this form');
+
+ const ConfirmButton = await waitFor(() => getByTestId('ok-button'));
+ fireEvent.click(ConfirmButton);
+
+ await waitFor(() => {
+ expect(errorSpy).toHaveBeenCalled();
+ });
+ });
+
+ test('deactivate a form successfully when inactive button is clicked', async () => {
+ const { getByText, getAllByRole, getByTestId } = render(wrapper([deactivateWhatsappForm]));
+ const notificationSpy = vi.spyOn(Notification, 'setNotification');
+
+ const select = getAllByRole('combobox')[0];
+ fireEvent.click(getByText('All'));
+
+ expect(select).toHaveTextContent('All');
+
+ expect(getByTestId('loading')).toBeInTheDocument();
+
+ await waitFor(() => {
+ expect(getByText('This is form name')).toBeInTheDocument();
+ });
+
+ fireEvent.click(getByTestId('MoreIcon'));
+ fireEvent.click(getByText('Deactivate'));
+
+ await waitFor(() => {
+ expect(getByTestId('dialogTitle')).toBeInTheDocument();
+ });
+
+ expect(getByTestId('dialogTitle')).toHaveTextContent('Do you want to deactivate this form?');
+
+ const ConfirmButton = await waitFor(() => getByTestId('ok-button'));
+ fireEvent.click(ConfirmButton);
+ await waitFor(() => {
+ expect(notificationSpy).toHaveBeenCalled();
+ });
+ });
+
+ test('shows error message when deactivate API fails', async () => {
+ const { getByText, getAllByRole, getByTestId } = render(wrapper([deactivateWhatsappFormError]));
+ const errorSpy = vi.spyOn(Notification, 'setErrorMessage');
+
+ const select = getAllByRole('combobox')[0];
+ fireEvent.click(getByText('All'));
+
+ expect(select).toHaveTextContent('All');
+
+ expect(getByTestId('loading')).toBeInTheDocument();
+
+ await waitFor(() => {
+ expect(getByText('This is form name')).toBeInTheDocument();
+ });
+
+ fireEvent.click(getByTestId('MoreIcon'));
+ fireEvent.click(getByText('Deactivate'));
+
+ await waitFor(() => {
+ expect(getByTestId('dialogTitle')).toBeInTheDocument();
+ });
+
+ expect(getByTestId('dialogTitle')).toHaveTextContent('Do you want to deactivate this form?');
+
+ const ConfirmButton = await waitFor(() => getByTestId('ok-button'));
+ fireEvent.click(ConfirmButton);
+
+ await waitFor(() => {
+ expect(errorSpy).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx b/src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx
new file mode 100644
index 0000000000..9aaa8fe4a0
--- /dev/null
+++ b/src/containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList.tsx
@@ -0,0 +1,261 @@
+import { useMutation } from '@apollo/client';
+import { FormControl, MenuItem, Select } from '@mui/material';
+import PublishIcon from 'assets/images/icons/Publish/PublishGray.svg?react';
+import { whatsappFormsInfo } from 'common/HelpData';
+import { setErrorMessage, setNotification } from 'common/notification';
+import { DialogBox } from 'components/UI/DialogBox/DialogBox';
+import { List } from 'containers/List/List';
+import { ACTIVATE_FORM, DEACTIVATE_FORM, DELETE_FORM, PUBLISH_FORM } from 'graphql/mutations/WhatsAppForm';
+import { GET_WHATSAPP_FORM, LIST_WHATSAPP_FORMS } from 'graphql/queries/WhatsAppForm';
+import { useMemo, useState } from 'react';
+import { useNavigate } from 'react-router';
+import styles from './WhatsAppFormList.module.css';
+
+const columnStyles = [styles.Name, styles.status, styles.Label, styles.Actions];
+
+const queries = {
+ filterItemsQuery: LIST_WHATSAPP_FORMS,
+ deleteItemQuery: DELETE_FORM,
+ getItemQuery: GET_WHATSAPP_FORM,
+ publishFlowQuery: PUBLISH_FORM,
+};
+
+const getName = (name: string) => {name}
;
+
+const getStatus = (status: string) => {
+ if (status === 'PUBLISHED') {
+ return Published
;
+ } else if (status === 'DRAFT') {
+ return Draft
;
+ } else if (status === 'INACTIVE') {
+ return Inactive
;
+ }
+};
+
+const getCategories = (categories: string[]) => {
+ if (!categories?.length) return null;
+
+ const displayedCategories = categories.slice(0, 2);
+ const hiddenCategories = categories.slice(2);
+
+ return (
+
+
+ {displayedCategories.map((category) => (
+
+ {category}
+
+ ))}
+
+ {categories.length > 2 && (
+
+
+ {categories.length - 2} more
+
+ {hiddenCategories.map((category) => (
+
+ {category}
+
+ ))}
+
+
+ )}
+
+
+ );
+};
+
+export const WhatsAppFormList = () => {
+ const [formId, setFormId] = useState(null);
+ const [dialogType, setDialogType] = useState<'publish' | 'inactive' | 'activate' | null>(null);
+ const [filter, setFilter] = useState('all');
+
+ const navigate = useNavigate();
+
+ const [publishForm, { loading: publishLoading }] = useMutation(PUBLISH_FORM, {
+ onCompleted: () => {
+ setFormId(null);
+ setDialogType(null);
+ setNotification('Form published successfully');
+ },
+ onError: (errors) => {
+ setErrorMessage(errors);
+ },
+ });
+
+ const [activateForm, { loading: activateFormLoading }] = useMutation(ACTIVATE_FORM, {
+ onCompleted: () => {
+ setFormId(null);
+ setDialogType(null);
+ setNotification('Form activated successfully');
+ },
+ onError: (errors) => {
+ setErrorMessage(errors);
+ },
+ });
+
+ const [deactivateForm, { loading: deactivateLoading }] = useMutation(DEACTIVATE_FORM, {
+ onCompleted: () => {
+ setFormId(null);
+ setDialogType(null);
+ setNotification('Form deactivated successfully');
+ },
+ onError: (errors) => {
+ setErrorMessage(errors);
+ },
+ });
+
+ const columnNames = [
+ { name: 'name', label: 'Name' },
+ { name: 'status', label: 'Status' },
+ { name: 'category', label: 'Category' },
+ { name: 'actions', label: 'Actions' },
+ ];
+
+ const getColumns = ({ name, categories, status }: any) => ({
+ name: getName(name),
+ status: getStatus(status),
+ category: getCategories(categories),
+ });
+
+ const filterList = [
+ { label: 'All', value: 'all' },
+ { label: 'Published', value: 'published' },
+ { label: 'Inactive', value: 'inactive' },
+ { label: 'Draft', value: 'draft' },
+ ];
+
+ const additionalAction = (item: any) => {
+ const deactivateAction = {
+ label: 'Deactivate',
+ parameter: 'id',
+ dialog: (id: string) => {
+ setFormId(id);
+ setDialogType('inactive');
+ },
+ insideMore: true,
+ };
+
+ const publishAction = {
+ label: 'Publish',
+ icon: ,
+ parameter: 'id',
+ dialog: (id: string) => {
+ setFormId(id);
+ setDialogType('publish');
+ },
+ };
+
+ const activateAction = {
+ label: 'Activate',
+ parameter: 'id',
+ dialog: (id: string) => {
+ setFormId(id);
+ setDialogType('activate');
+ activateForm({ variables: { activateWhatsappFormId: id } });
+ },
+ insideMore: true,
+ };
+
+ let actions = [];
+
+ if (item.status === 'PUBLISHED') {
+ actions = [deactivateAction];
+ } else if (item.status === 'DRAFT') {
+ actions = [publishAction];
+ } else {
+ actions = [activateAction];
+ }
+
+ return actions;
+ };
+ const filters = useMemo(() => {
+ let filters: any = {};
+ if (filter !== 'all') {
+ filters = { status: filter.toUpperCase() };
+ }
+ return filters;
+ }, [filter]);
+
+ const formFilter = (
+
+
+
+ );
+
+ let dialog = null;
+ if (formId && dialogType) {
+ const handleOk = () => {
+ if (dialogType === 'publish') {
+ publishForm({ variables: { id: formId } });
+ } else if (dialogType === 'inactive') {
+ deactivateForm({ variables: { id: formId } });
+ }
+ };
+
+ let dialogTitle = '';
+ let dialogText = '';
+
+ if (dialogType === 'publish') {
+ dialogTitle = 'Do you want to publish this form?';
+ dialogText = 'The form will be published on Meta and made visible to users.';
+ } else if (dialogType === 'inactive') {
+ dialogTitle = 'Do you want to deactivate this form?';
+ dialogText = 'The form will be marked inactive and cannot be used.';
+ }
+
+ dialog = (
+ {
+ setFormId(null);
+ setDialogType(null);
+ }}
+ alignButtons="center"
+ buttonOkLoading={deactivateLoading || activateFormLoading || publishLoading}
+ >
+ {dialogText}
+
+ );
+ }
+
+ return (
+ <>
+ navigate('/whatsapp-forms/add') }}
+ searchParameter={['name']}
+ additionalAction={additionalAction}
+ dialogMessage={'The form will be permanently deleted and cannot be recovered.'}
+ />
+ {dialog}
+ >
+ );
+};
+
+export default WhatsAppFormList;
diff --git a/src/containers/WhatsAppForms/WhatsAppForms.tsx b/src/containers/WhatsAppForms/WhatsAppForms.tsx
new file mode 100644
index 0000000000..174e4aaa82
--- /dev/null
+++ b/src/containers/WhatsAppForms/WhatsAppForms.tsx
@@ -0,0 +1,217 @@
+import { useQuery } from '@apollo/client';
+import OpenInNew from '@mui/icons-material/OpenInNew';
+import Update from '@mui/icons-material/Update';
+import { useState } from 'react';
+import * as Yup from 'yup';
+
+import { whatsappFormsInfo } from 'common/HelpData';
+import { AutoComplete } from 'components/UI/Form/AutoComplete/AutoComplete';
+import { Button } from 'components/UI/Form/Button/Button';
+import { Input } from 'components/UI/Form/Input/Input';
+import { Heading } from 'components/UI/Heading/Heading';
+import { Loading } from 'components/UI/Layout/Loading/Loading';
+import setLogs from 'config/logs';
+import { FormLayout } from 'containers/Form/FormLayout';
+import { CREATE_FORM, DELETE_FORM, UPDATE_FORM } from 'graphql/mutations/WhatsAppForm';
+import { GET_WHATSAPP_FORM, LIST_FORM_CATEGORIES } from 'graphql/queries/WhatsAppForm';
+import { useParams } from 'react-router';
+import styles from './WhatsAppForm.module.css';
+
+const queries = {
+ getItemQuery: GET_WHATSAPP_FORM,
+ createItemQuery: CREATE_FORM,
+ updateItemQuery: UPDATE_FORM,
+ deleteItemQuery: DELETE_FORM,
+};
+
+export const WhatsAppForms = () => {
+ 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();
+
+ useQuery(GET_WHATSAPP_FORM, {
+ skip: !params.id,
+ variables: { id: params.id },
+ onCompleted: ({ whatsappForm }) => {
+ if (whatsappForm?.whatsappForm?.status === 'PUBLISHED') {
+ setDisabled(true);
+ }
+ },
+ });
+
+ let isEditing = false;
+ if (params.id) {
+ isEditing = true;
+ }
+
+ const { loading } = useQuery(LIST_FORM_CATEGORIES, {
+ onCompleted: ({ whatsappFormCategories }) => {
+ setCategories(
+ whatsappFormCategories.map((category: string) => ({
+ id: category,
+ name: category
+ .toLowerCase()
+ .replace(/_/g, ' ')
+ .replace(/\b\w/g, (c) => c.toUpperCase()),
+ }))
+ );
+ },
+ });
+
+ const states = {
+ name,
+ formJson: JSON.stringify(formJson),
+ formCategories,
+ description,
+ };
+
+ const setPayload = ({ name, formJson, formCategories, description }: any) => {
+ const payload = {
+ name,
+ formJson,
+ description,
+ categories: formCategories.map((category: any) => category.id),
+ };
+
+ return payload;
+ };
+ 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);
+ };
+ const formFields = [
+ {
+ component: Input,
+ name: 'name',
+ type: 'text',
+ label: `${'Title'}*`,
+ placeholder: 'Enter form title',
+ disabled: disabled,
+ },
+ {
+ component: Input,
+ name: 'description',
+ type: 'text',
+ label: `${'Description'}`,
+ textArea: true,
+ rows: 2,
+ placeholder: 'Enter form description',
+ disabled: disabled,
+ },
+ {
+ component: Input,
+ name: 'formJson',
+ type: 'text',
+ label: 'Form JSON*',
+ textArea: true,
+ rows: 6,
+ placeholder: 'Paste your JSON from Meta flow builder here...',
+ disabled: disabled,
+ },
+ {
+ component: AutoComplete,
+ name: 'formCategories',
+ options: categories,
+ optionLabel: 'name',
+ label: 'Categories',
+ placeholder: 'Select categories',
+ helperText:
+ 'Choose categories that represent your form. Multiple values are possible, but at least one is required.',
+ disabled: disabled,
+ },
+ ];
+ const FormSchema = Yup.object().shape({
+ name: Yup.string().required('Title is required.').max(50, 'Title is too long.'),
+
+ formJson: Yup.string()
+ .required('Form JSON is required.')
+ .test('is-json', 'Must be valid JSON', (value) => {
+ if (!value) return false;
+ try {
+ JSON.parse(value);
+ return true;
+ } catch (error) {
+ return false;
+ }
+ }),
+
+ formCategories: Yup.array().min(1, 'At least one category must be selected.'),
+ });
+
+ if (loading) {
+ return ;
+ }
+ return (
+ <>
+
+
+
+
+
+
+
+
First, create your flow in Meta Flow Builder
+
+ Design your WhatsApp Flow using Meta's visual builder, then copy the JSON and paste it below.
+
+
+
+
+
}
+ component="a"
+ onClick={() =>
+ window.open(
+ 'https://developers.facebook.com/docs/whatsapp/flows/playground',
+ '_blank',
+ 'noopener,noreferrer'
+ )
+ }
+ >
+ Open Flow Builder
+
+
+ }
+ helpData={whatsappFormsInfo}
+ backLinkButton={`/whatsapp-forms`}
+ noHeading
+ dialogMessage={'The form will be permanently deleted and cannot be recovered.'}
+ buttonState={{
+ text: 'Save Form',
+ status: disabled,
+ }}
+ />
+ >
+ );
+};
+
+export default WhatsAppForms;
diff --git a/src/graphql/mutations/WhatsAppForm.ts b/src/graphql/mutations/WhatsAppForm.ts
new file mode 100644
index 0000000000..e7fbd44a61
--- /dev/null
+++ b/src/graphql/mutations/WhatsAppForm.ts
@@ -0,0 +1,91 @@
+import { gql } from '@apollo/client';
+
+export const CREATE_FORM = gql`
+ mutation CreateWhatsappForm($input: WhatsappFormInput!) {
+ createWhatsappForm(input: $input) {
+ whatsappForm {
+ id
+ name
+ }
+ errors {
+ message
+ }
+ }
+ }
+`;
+
+export const UPDATE_FORM = gql`
+ mutation UpdateWhatsappForm($id: ID!, $input: WhatsappFormInput!) {
+ updateWhatsappForm(id: $id, input: $input) {
+ whatsappForm {
+ id
+ name
+ }
+ errors {
+ message
+ }
+ }
+ }
+`;
+
+export const DELETE_FORM = gql`
+ mutation DeleteWhatsappForm($id: ID!) {
+ deleteWhatsappForm(id: $id) {
+ whatsappForm {
+ id
+ }
+ errors {
+ message
+ }
+ }
+ }
+`;
+
+export const PUBLISH_FORM = gql`
+ mutation publishWhatsappForm($id: ID!) {
+ publishWhatsappForm(id: $id) {
+ whatsappForm {
+ id
+ status
+ }
+ errors {
+ message
+ }
+ }
+ }
+`;
+
+export const DEACTIVATE_FORM = gql`
+ mutation DeactivateWhatsappForm($id: ID!) {
+ deactivateWhatsappForm(id: $id) {
+ whatsappForm {
+ id
+ status
+ }
+ errors {
+ message
+ }
+ }
+ }
+`;
+
+export const ACTIVATE_FORM = gql`
+ mutation ActivateWhatsappForm($activateWhatsappFormId: ID!) {
+ activateWhatsappForm(id: $activateWhatsappFormId) {
+ whatsappForm {
+ categories
+ definition
+ description
+ id
+ insertedAt
+ metaFlowId
+ name
+ status
+ updatedAt
+ }
+ errors {
+ message
+ }
+ }
+ }
+`;
diff --git a/src/graphql/queries/Organization.ts b/src/graphql/queries/Organization.ts
index 0d78e07f06..1b25e1964f 100644
--- a/src/graphql/queries/Organization.ts
+++ b/src/graphql/queries/Organization.ts
@@ -136,6 +136,7 @@ export const GET_ORGANIZATION_SERVICES = gql`
whatsappGroupEnabled
certificateEnabled
askMeBotEnabled
+ whatsappFormsEnabled
}
}
`;
diff --git a/src/graphql/queries/Search.ts b/src/graphql/queries/Search.ts
index 6bd84f7fdb..1ce428e025 100644
--- a/src/graphql/queries/Search.ts
+++ b/src/graphql/queries/Search.ts
@@ -69,6 +69,10 @@ export const SEARCH_QUERY = gql`
interactiveContent
sendBy
flowLabel
+ whatsappFormResponse {
+ rawResponse
+ whatsappFormId
+ }
}
}
}
diff --git a/src/graphql/queries/WhatsAppForm.ts b/src/graphql/queries/WhatsAppForm.ts
new file mode 100644
index 0000000000..194558cb40
--- /dev/null
+++ b/src/graphql/queries/WhatsAppForm.ts
@@ -0,0 +1,39 @@
+import { gql } from '@apollo/client';
+
+export const GET_WHATSAPP_FORM = gql`
+ query WhatsappForm($id: ID!) {
+ whatsappForm(id: $id) {
+ whatsappForm {
+ definition
+ description
+ categories
+ id
+ insertedAt
+ metaFlowId
+ name
+ status
+ updatedAt
+ }
+ }
+ }
+`;
+
+export const LIST_FORM_CATEGORIES = gql`
+ query {
+ whatsappFormCategories
+ }
+`;
+
+export const LIST_WHATSAPP_FORMS = gql`
+ query listWhatsappForms($filter: WhatsappFormFilter) {
+ listWhatsappForms(filter: $filter) {
+ id
+ name
+ status
+ description
+ metaFlowId
+ categories
+ definition
+ }
+ }
+`;
diff --git a/src/graphql/subscriptions/Chat.ts b/src/graphql/subscriptions/Chat.ts
index 06a7850078..e415879e84 100644
--- a/src/graphql/subscriptions/Chat.ts
+++ b/src/graphql/subscriptions/Chat.ts
@@ -59,6 +59,10 @@ export const MESSAGE_RECEIVED_SUBSCRIPTION = gql`
interactiveContent
flowLabel
sendBy
+ whatsappFormResponse {
+ rawResponse
+ whatsappFormId
+ }
}
}
`;
@@ -119,6 +123,10 @@ export const MESSAGE_SENT_SUBSCRIPTION = gql`
interactiveContent
flowLabel
sendBy
+ whatsappFormResponse {
+ rawResponse
+ whatsappFormId
+ }
}
}
`;
diff --git a/src/i18n/en/en.json b/src/i18n/en/en.json
index 5e1839cab4..eab0bfb78e 100644
--- a/src/i18n/en/en.json
+++ b/src/i18n/en/en.json
@@ -10,6 +10,8 @@
"Session message window has expired! You can only send a template message now.": "Session message window has expired! You can only send a template message now.",
"Your message window is about to expire!": "Your message window is about to expire!",
"or": "or",
+ "Form Name": "Form Name",
+ "Last Updated": "Last Updated",
"We are unable to generate an OTP, kindly contact your technical team.": "We are unable to generate an OTP, kindly contact your technical team.",
"Please confirm the OTP received at your WhatsApp number.": "Please confirm the OTP received at your WhatsApp number.",
"We are unable to register, kindly contact your technical team.": "We are unable to register, kindly contact your technical team.",
@@ -552,7 +554,6 @@
"It will not be possible to update the number later. The new number will be {{phone}}.": "It will not be possible to update the number later. The new number will be {{phone}}.",
"Only lowercase alphanumeric characters and underscores are allowed.": "Only lowercase alphanumeric characters and underscores are allowed.",
"Share": "Share",
- "Last Updated": "Last Updated",
"Draft": "Draft",
"Published": "Published",
"Last Published At": "Last Published At"
diff --git a/src/mocks/Chat.tsx b/src/mocks/Chat.tsx
index 49eae8b028..2f904bb914 100644
--- a/src/mocks/Chat.tsx
+++ b/src/mocks/Chat.tsx
@@ -66,6 +66,7 @@ export const sampleMessages = {
sendBy: 'Glific User',
interactiveContent: '{}',
flowLabel: null,
+ whatsappFormResponse: null,
};
export const conversationMessageQuery = (
@@ -168,6 +169,7 @@ export const conversationCollectionQuery = (
interactiveContent: '{}',
sendBy: 'test',
flowLabel: null,
+ whatsappFormResponse: null,
},
{
id: '1',
@@ -204,6 +206,7 @@ export const conversationCollectionQuery = (
interactiveContent: '{}',
sendBy: 'test',
flowLabel: null,
+ whatsappFormResponse: null,
},
],
},
@@ -531,6 +534,7 @@ export const conversationQuery = getConversationQuery({
interactiveContent: '{}',
sendBy: 'test',
flowLabel: null,
+ whatsappFormResponse: null,
},
{
id: '2',
@@ -567,6 +571,7 @@ export const conversationQuery = getConversationQuery({
interactiveContent: '{}',
sendBy: 'test',
flowLabel: null,
+ whatsappFormResponse: null,
},
],
},
@@ -640,6 +645,7 @@ const conversation = {
},
],
id: 'contact_2',
+ whatsappFormResponse: null,
},
],
};
@@ -671,6 +677,7 @@ const conversationWithMultipleMessages = {
},
type: 'TEXT',
media: null,
+ whatsappFormResponse: null,
},
{
body: 'Yo',
@@ -684,6 +691,7 @@ const conversationWithMultipleMessages = {
},
type: 'TEXT',
media: null,
+ whatsappFormResponse: null,
},
],
},
@@ -798,6 +806,7 @@ const searchQueryResult = {
interactiveContent: '{}',
sendBy: 'test',
flowLabel: null,
+ whatsappFormResponse: null,
},
],
},
@@ -931,6 +940,7 @@ export const loadMoreChats = {
id: '2',
},
type: 'TEXT',
+ whatsappFormResponse: null,
},
],
},
diff --git a/src/mocks/Search.tsx b/src/mocks/Search.tsx
index cd15194b76..e82a1352c3 100644
--- a/src/mocks/Search.tsx
+++ b/src/mocks/Search.tsx
@@ -499,6 +499,7 @@ export const getContactSearchQuery = {
id: '1',
},
type: 'TEXT',
+ whatsappFormResponse: null,
},
],
},
@@ -562,6 +563,7 @@ export const messages = (limit: number, skip: number) =>
interactiveContent: '{}',
sendBy: 'test',
flowLabel: null,
+ whatsappFormResponse: null,
}));
export const searchQuery = {
diff --git a/src/mocks/Template.tsx b/src/mocks/Template.tsx
index ffb98e8a83..30a1cd79e7 100644
--- a/src/mocks/Template.tsx
+++ b/src/mocks/Template.tsx
@@ -233,6 +233,50 @@ export const getHSMTemplateTypeMedia = {
data: getTemplateDataTypeMedia,
},
};
+export const CREATE_SESSION_TEMPLATE_MOCK = [
+ {
+ request: {
+ query: CREATE_TEMPLATE,
+ },
+ result: () => ({
+ data: {
+ createSessionTemplate: {
+ sessionTemplate: {
+ id: '101',
+ label: 'title',
+ body: 'Hi, How are you*_~~_* {{1}}',
+ footer: 'footer',
+ isActive: true,
+ language: {
+ id: '1',
+ label: 'English',
+ },
+ translations: [],
+ type: 'TEXT',
+ MessageMedia: null,
+ category: 'ACCOUNT_UPDATE',
+ shortcode: 'element_name',
+ example: 'Hi, How are you*_~~_* [User]',
+ hasButtons: true,
+ buttons: JSON.stringify([
+ {
+ type: 'FLOW',
+ navigate_screen: 'RECOMMEND',
+ text: 'Continue',
+ flow_id: '1473834353902269',
+ flow_action: 'NAVIGATE',
+ },
+ ]),
+ buttonType: 'WHATSAPP_FORM',
+ },
+ errors: null,
+ },
+ },
+ }),
+ maxUsageCount: Number.POSITIVE_INFINITY,
+ variableMatcher: () => true,
+ },
+];
export const createTemplateMock = (input: any) => ({
request: {
@@ -479,7 +523,6 @@ export const getSpeedSendTemplate2 = {
},
},
};
-
export const updateSessiontemplate = {
request: {
query: UPDATE_TEMPLATE,
diff --git a/src/mocks/WhatsAppForm.tsx b/src/mocks/WhatsAppForm.tsx
new file mode 100644
index 0000000000..fdbac4ca62
--- /dev/null
+++ b/src/mocks/WhatsAppForm.tsx
@@ -0,0 +1,308 @@
+import { CREATE_FORM, UPDATE_FORM, PUBLISH_FORM, DEACTIVATE_FORM } from 'graphql/mutations/WhatsAppForm';
+import { GET_WHATSAPP_FORM, LIST_FORM_CATEGORIES, LIST_WHATSAPP_FORMS } from 'graphql/queries/WhatsAppForm';
+
+export const formJson = {
+ version: '7.2',
+ screens: [
+ {
+ id: 'RECOMMEND',
+ title: 'Feedback 1 of 2',
+ data: {},
+ layout: {},
+ },
+ {
+ id: 'RATE',
+ title: 'Feedback 2 of 2',
+ data: {},
+ terminal: true,
+ success: true,
+ layout: {},
+ },
+ ],
+};
+
+const whatsappFormCategories = {
+ request: {
+ query: LIST_FORM_CATEGORIES,
+ variables: {},
+ },
+ result: {
+ data: {
+ whatsappFormCategories: [
+ 'sign_up',
+ 'sign_in',
+ 'appointment_booking',
+ 'lead_generation',
+ 'contact_us',
+ 'customer_support',
+ 'survey',
+ 'other',
+ ],
+ },
+ },
+};
+
+const createdWhatsAppFormQuery = {
+ request: {
+ query: CREATE_FORM,
+ variables: {
+ input: {
+ name: 'Test Form',
+ formJson: JSON.stringify(formJson),
+ description: 'This is a test form',
+ categories: ['other'],
+ },
+ },
+ },
+ result: {
+ data: {
+ createWhatsappForm: {
+ whatsappForm: {
+ id: '1',
+ name: 'Test Form',
+ },
+ errors: null,
+ },
+ },
+ },
+};
+export const publishWhatsappForm = {
+ request: {
+ query: PUBLISH_FORM,
+ variables: {
+ id: '3',
+ },
+ },
+ result: {
+ data: {
+ publishWhatsappForm: {
+ id: '1',
+ status: 'PUBLISHED',
+ },
+ },
+ },
+};
+
+export const deactivateWhatsappForm = {
+ request: {
+ query: DEACTIVATE_FORM,
+ variables: {
+ id: '3',
+ },
+ },
+ result: {
+ data: {
+ publishWhatsappForm: {
+ id: '1',
+ status: 'inactive',
+ __typename: 'WhatsappForm',
+ },
+ },
+ },
+};
+export const publishWhatsappFormError = {
+ request: {
+ query: PUBLISH_FORM,
+ variables: {
+ id: '3',
+ },
+ },
+ error: new Error('Failed to publish'),
+};
+
+export const deactivateWhatsappFormError = {
+ request: {
+ query: DEACTIVATE_FORM,
+ variables: {
+ id: '3',
+ },
+ },
+ error: new Error('Failed to publish'),
+};
+const listWhatsappForms = {
+ request: {
+ query: LIST_WHATSAPP_FORMS,
+ variables: {
+ filter: { status: 'PUBLISHED' },
+ opts: { limit: 50, offset: 0, order: 'ASC', orderWith: 'name' },
+ },
+ },
+ result: {
+ data: {
+ listWhatsappForms: [
+ {
+ id: '1',
+ name: 'This is form name',
+ status: 'PUBLISHED',
+ description: 'This is test form',
+ metaFlowId: '1473834353902269',
+ categories: ['customer_support'],
+ definition: JSON.stringify(formJson),
+ },
+ ],
+ },
+ },
+};
+
+const listWhatsappFormswithoutopts = {
+ request: {
+ query: LIST_WHATSAPP_FORMS,
+ variables: {
+ filter: { status: 'PUBLISHED' },
+ },
+ },
+ result: {
+ data: {
+ listWhatsappForms: [
+ {
+ id: '1',
+ name: 'This is form name',
+ status: 'PUBLISHED',
+ description: 'This is test form',
+ metaFlowId: '1473834353902269',
+ categories: ['customer_support'],
+ definition: JSON.stringify(formJson),
+ },
+ ],
+ },
+ },
+};
+const listWhatsappFormsInactive = {
+ request: {
+ query: LIST_WHATSAPP_FORMS,
+ variables: {
+ filter: { status: 'INACTIVE' },
+ opts: { limit: 50, offset: 0, order: 'ASC', orderWith: 'name' },
+ },
+ },
+ result: {
+ data: {
+ listWhatsappForms: [
+ {
+ id: '2',
+ name: 'This is form name',
+ status: 'INACTIVE',
+ description: 'This is test form',
+ metaFlowId: '1473834353902269',
+ categories: ['customer_support'],
+ definition: JSON.stringify(formJson),
+ },
+ ],
+ },
+ },
+};
+
+const listWhatsappFormsDraft = {
+ request: {
+ query: LIST_WHATSAPP_FORMS,
+ variables: {
+ filter: { status: 'DRAFT' },
+ opts: { limit: 50, offset: 0, order: 'ASC', orderWith: 'name' },
+ },
+ },
+ result: {
+ data: {
+ listWhatsappForms: [
+ {
+ id: '3',
+ name: 'This is form name',
+ status: 'DRAFT',
+ description: 'This is test form',
+ metaFlowId: '1473834353902269',
+ categories: ['customer_support'],
+ definition: JSON.stringify(formJson),
+ },
+ ],
+ },
+ },
+};
+const listWhatsappFormsEmpty = {
+ request: {
+ query: LIST_WHATSAPP_FORMS,
+ variables: {
+ filter: {},
+ opts: { limit: 50, offset: 0, order: 'ASC', orderWith: 'name' },
+ },
+ },
+ result: {
+ data: {
+ listWhatsappForms: [
+ {
+ id: '3',
+ name: 'This is form name',
+ status: 'PUBLISHED',
+ description: 'This is test form',
+ metaFlowId: '1473834353902269',
+ categories: ['customer_support'],
+ definition: JSON.stringify(formJson),
+ },
+ ],
+ },
+ },
+};
+
+const getWhatsAppForm = {
+ request: {
+ query: GET_WHATSAPP_FORM,
+ variables: {
+ id: '1',
+ },
+ },
+ result: {
+ data: {
+ whatsappForm: {
+ whatsappForm: {
+ categories: ['customer_support'],
+ definition: JSON.stringify(formJson),
+ description: 'This is test form',
+ id: '1',
+ insertedAt: '2025-11-06 09:31:19.955920Z',
+ metaFlowId: '1473834353902269',
+ name: 'This is form name',
+ status: 'DRAFT',
+ updatedAt: '2025-11-06 09:31:39.104993Z',
+ },
+ },
+ },
+ },
+};
+
+const editWhatsAppForm = {
+ request: {
+ query: UPDATE_FORM,
+ variables: {
+ id: '1',
+ input: {
+ name: 'This is form name',
+ formJson: JSON.stringify(formJson),
+ description: 'This is an updated test form',
+ categories: ['customer_support'],
+ },
+ },
+ },
+ result: {
+ data: {
+ updateWhatsappForm: {
+ __typename: 'WhatsappFormResult',
+ errors: null,
+ whatsappForm: {
+ __typename: 'WhatsappForm',
+ id: '1',
+ name: 'This is form name',
+ },
+ },
+ },
+ },
+};
+
+export const WHATSAPP_FORM_MOCKS = [
+ whatsappFormCategories,
+ createdWhatsAppFormQuery,
+ getWhatsAppForm,
+ editWhatsAppForm,
+ listWhatsappForms,
+ listWhatsappFormsInactive,
+ listWhatsappFormsDraft,
+ listWhatsappFormsEmpty,
+ listWhatsappFormswithoutopts,
+];
diff --git a/src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx b/src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx
index b10db72197..e5bd16ac86 100644
--- a/src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx
+++ b/src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx
@@ -68,6 +68,8 @@ const WaPollsList = lazy(() => import('containers/WaGroups/WaPolls/WaPollsList/W
const Certificates = lazy(() => import('containers/Certificates/Certificate'));
const CertificatesList = lazy(() => import('containers/Certificates/CertificatesList/CertificateList'));
+const WhatsAppFormsList = lazy(() => import('containers/WhatsAppForms/WhatsAppFormList/WhatsAppFormList'));
+const WhatsAppForms = lazy(() => import('containers/WhatsAppForms/WhatsAppForms'));
const routeStaff = (
@@ -159,6 +161,11 @@ const routeAdmin = (
} />
} />
} />
+
+ } />
+ } />
+ } />
+
} />
diff --git a/src/services/AuthService.tsx b/src/services/AuthService.tsx
index 744d24379a..c5e356c41c 100644
--- a/src/services/AuthService.tsx
+++ b/src/services/AuthService.tsx
@@ -21,7 +21,8 @@ type ServiceType =
| 'ticketingEnabled'
| 'whatsappGroupEnabled'
| 'certificateEnabled'
- | 'askMeBotEnabled';
+ | 'askMeBotEnabled'
+ | 'whatsappFormsEnabled';
// get the current authentication session
export const getAuthSession = (element?: string) => {