diff --git a/.github/instructions/aselo-webchat-react-app.instructions.md b/.github/instructions/aselo-webchat-react-app.instructions.md index f25ea100fe..82905b7c08 100644 --- a/.github/instructions/aselo-webchat-react-app.instructions.md +++ b/.github/instructions/aselo-webchat-react-app.instructions.md @@ -5,6 +5,7 @@ excludeAgent: "code-review" Always run the following checks and fix any issues they raise prior to requesting a review: +- Ensure the necessary dependencies are properly installed running `npm ci` in aselo-webchat-react-app/ - Ensure the typescript compiles by running the build command in aselo-webchat-react-app/package.json - Ensure the unit tests pass by running the test script in aselo-webchat-react-app/package.json - Ensure the code changes are correctly linted by running eslint using the configuration in the aselo-webchat-react-app directory diff --git a/aselo-webchat-react-app/package-lock.json b/aselo-webchat-react-app/package-lock.json index 1a99023570..d933e00bbd 100644 --- a/aselo-webchat-react-app/package-lock.json +++ b/aselo-webchat-react-app/package-lock.json @@ -31416,23 +31416,6 @@ } } }, - "node_modules/tailwindcss/node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/tapable": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", diff --git a/aselo-webchat-react-app/src/__mocks__/redux/mockRedux.ts b/aselo-webchat-react-app/src/__mocks__/redux/mockRedux.ts index 788adf717a..644a027aed 100644 --- a/aselo-webchat-react-app/src/__mocks__/redux/mockRedux.ts +++ b/aselo-webchat-react-app/src/__mocks__/redux/mockRedux.ts @@ -54,6 +54,7 @@ export const BASE_MOCK_REDUX: AppState = { session: { expanded: false, currentPhase: EngagementPhase.Loading, + preEngagementData: {}, }, }; diff --git a/aselo-webchat-react-app/src/components/ConversationEnded.tsx b/aselo-webchat-react-app/src/components/ConversationEnded.tsx index 2ecd21939f..9c5fc55f7f 100644 --- a/aselo-webchat-react-app/src/components/ConversationEnded.tsx +++ b/aselo-webchat-react-app/src/components/ConversationEnded.tsx @@ -32,7 +32,7 @@ export const ConversationEnded = () => { const handleStartNewChat = () => { sessionDataHandler.clear(); - dispatch(updatePreEngagementData({ email: '', name: '', query: '' })); + dispatch(updatePreEngagementData({})); dispatch(changeEngagementPhase({ phase: EngagementPhase.PreEngagementForm })); }; diff --git a/aselo-webchat-react-app/src/components/MessagingCanvasPhase.tsx b/aselo-webchat-react-app/src/components/MessagingCanvasPhase.tsx index 3fb30887ca..ca3b016ccb 100644 --- a/aselo-webchat-react-app/src/components/MessagingCanvasPhase.tsx +++ b/aselo-webchat-react-app/src/components/MessagingCanvasPhase.tsx @@ -50,7 +50,7 @@ export const MessagingCanvasPhase = () => { useEffect(() => { dispatch(removeNotification(notifications.failedToInitSessionNotification('ds').id)); - sendInitialUserQuery(conversation as Conversation, preEngagmentData?.query); + sendInitialUserQuery(conversation as Conversation, 'TODO: trigger message'); }, [dispatch, conversation, preEngagmentData]); const Wrapper = conversationState === 'active' ? AttachFileDropArea : Fragment; diff --git a/aselo-webchat-react-app/src/components/PreEngagementFormPhase.tsx b/aselo-webchat-react-app/src/components/PreEngagementFormPhase.tsx index 3fd9f4c52c..1082f7ca7d 100644 --- a/aselo-webchat-react-app/src/components/PreEngagementFormPhase.tsx +++ b/aselo-webchat-react-app/src/components/PreEngagementFormPhase.tsx @@ -14,29 +14,35 @@ * along with this program. If not, see https://www.gnu.org/licenses/. */ -import { Input } from '@twilio-paste/core/input'; -import { Label } from '@twilio-paste/core/label'; import { Box } from '@twilio-paste/core/box'; -import { TextArea } from '@twilio-paste/core/textarea'; import { FormEvent } from 'react'; import { Button } from '@twilio-paste/core/button'; import { useDispatch, useSelector } from 'react-redux'; import { Text } from '@twilio-paste/core/text'; import { sessionDataHandler } from '../sessionDataHandler'; -import { addNotification, changeEngagementPhase, updatePreEngagementData } from '../store/actions/genericActions'; +import { addNotification, changeEngagementPhase, updatePreEngagementDataField } from '../store/actions/genericActions'; import { initSession } from '../store/actions/initActions'; import { AppState, EngagementPhase } from '../store/definitions'; import { Header } from './Header'; import { notifications } from '../notifications'; import { NotificationBar } from './NotificationBar'; -import { introStyles, fieldStyles, titleStyles, formStyles } from './styles/PreEngagementFormPhase.styles'; -import { useSanitizer } from '../utils/useSanitizer'; +import { fieldStyles, titleStyles, formStyles } from './styles/PreEngagementFormPhase.styles'; +import LocalizedTemplate from '../localization/LocalizedTemplate'; +import { generateForm } from './forms/formInputs'; export const PreEngagementFormPhase = () => { - const { name, email, query } = useSelector((state: AppState) => state.session.preEngagementData) || {}; + const { preEngagementData } = useSelector((state: AppState) => state.session ?? {}); + const { preEngagementFormDefinition } = useSelector((state: AppState) => state.config); const dispatch = useDispatch(); - const { onUserInputSubmit } = useSanitizer(); + + const { friendlyName } = preEngagementData; + + const getItem = (inputName: string) => preEngagementData[inputName] ?? {}; + const setItemValue = (payload: { name: string; value: string | boolean }) => { + dispatch(updatePreEngagementDataField(payload)); + }; + const handleChange = setItemValue; const handleSubmit = async (e: FormEvent) => { e.preventDefault(); @@ -44,9 +50,8 @@ export const PreEngagementFormPhase = () => { try { const data = await sessionDataHandler.fetchAndStoreNewSession({ formData: { - friendlyName: name && onUserInputSubmit(name, true), - email, - query: query && onUserInputSubmit(query), + ...preEngagementData, + friendlyName, }, }); dispatch( @@ -61,12 +66,12 @@ export const PreEngagementFormPhase = () => { } }; - const handleKeyPress = (e: React.KeyboardEvent) => { - if (e.key === 'Enter' && !e.shiftKey) { - e.preventDefault(); - handleSubmit(e); - } - }; + if (!preEngagementFormDefinition) { + return null; + } + + const titleText = preEngagementFormDefinition.description ?? 'Hi there!'; + const submitText = preEngagementFormDefinition.submitLabel ?? 'Start chat'; return ( <> @@ -74,52 +79,14 @@ export const PreEngagementFormPhase = () => { - Hi there! + - - We're here to help. Please give us some info to get started. - - - - dispatch(updatePreEngagementData({ name: e.target.value }))} - pattern="[A-Za-z0-9' ]{1,}" - required - /> - - - - dispatch(updatePreEngagementData({ email: e.target.value }))} - required - /> - - - -