@defra/flood-webchat 1.0.10 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js CHANGED
@@ -1 +1 @@
1
- (()=>{var e={792:(e,t,a)=>{const{DateTime:n}=a(168),o=e=>Number(e.split(":")[0]);e.exports={isWithinHours:(e,t)=>{const a=t?n.fromISO(t):n.local();a.setZone("Europe/London");const l=t?new Date(t):new Date,r=l.toLocaleDateString("en-GB",{weekday:"long"}),s=l.toLocaleDateString("en-GB").split("/"),c=e.find((e=>e.day===r)),i=n.local(Number(s[2]),Number(s[1]),Number(s[0]),o(c.openTime)),u=n.local(Number(s[2]),Number(s[1]),Number(s[0]),o(c.closeTime));return a.diff(i).milliseconds>=0&&a.diff(u).milliseconds<=0},stripPageTitle:e=>e.replace(/^\(\d+ new messages?\) - /,"")}},168:e=>{"use strict";e.exports=require("luxon")}},t={};function a(n){var o=t[n];if(void 0!==o)return o.exports;var l=t[n]={exports:{}};return e[n](l,l.exports,a),l.exports}a.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return a.d(t,{a:t}),t},a.d=(e,t)=>{for(var n in t)a.o(t,n)&&!a.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),a.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var n={};(()=>{"use strict";a.r(n),a.d(n,{init:()=>ce});const e=require("react");var t=a.n(e);const o=require("react-dom/client"),l=require("@nice-devone/nice-cxone-chat-web-sdk"),r="webchat_settings",s="webchat_customer_id",c="webchat_thread_id",i=4e3,u="message_unseen_count",d={SET_SDK:(e,t)=>({...e,sdk:t}),SET_THREAD:(e,t)=>({...e,thread:t}),SET_CHAT_VISIBILITY:(e,t)=>({...e,isChatOpen:t}),SET_AVAILABILITY:(e,t)=>({...e,availability:t}),SET_SETTINGS:(e,t)=>(t?window.localStorage.setItem(r,JSON.stringify(t)):window.localStorage.removeItem(r),{...e,settings:t}),SET_CUSTOMER_ID:(e,t)=>(t?window.localStorage.setItem(s,t):window.localStorage.removeItem(s),{...e,customerId:t}),SET_THREAD_ID:(e,t)=>(t?window.localStorage.setItem(c,t):window.localStorage.removeItem(c),{...e,threadId:t}),SET_UNSEEN_COUNT:(e,t)=>(window.localStorage.setItem(u,t),{...e,unseenCount:t}),SET_INSTIGATOR_ID:(e,t)=>({...e,instigatorId:t}),SET_LIVE_REGION_TEXT:(e,t)=>({...e,liveRegionText:t}),TOGGLE_IS_MOBILE:(e,t)=>({...e,isMobile:t}),TOGGLE_IS_KEYBOARD:(e,t)=>({...e,isKeyboard:t})},m={sdk:null,availability:null,customerId:null,threadId:null,thread:null,unseenCount:0,instigatorId:null,isChatOpen:!1,isMobile:window.matchMedia("(max-width: 640px)").matches,isKeyboard:!1,settings:{audio:!0,scroll:!0}},g=(e,t)=>{const{type:a,payload:n}=t,o=d[a];return o?o.bind(void 0,e,n)():e},E=(0,e.createContext)(m),h=({availability:a,children:n})=>{const[o,l]=(0,e.useReducer)(g,m);(0,e.useEffect)((()=>{l({type:"SET_AVAILABILITY",payload:a}),b(window.localStorage.getItem(s)),y(window.localStorage.getItem(c)),p(JSON.parse(window.localStorage.getItem(r))||o.settings),k(window.localStorage.getItem(u))}),[]),(0,e.useEffect)((()=>{"#webchat"===window.location.hash&&v(!0);const e=()=>{"#webchat"===window.location.hash?v(!0):v(!1)};return window.addEventListener("popstate",e),()=>{window.removeEventListener("popstate",e)}}),[]);const i=e=>{l({type:"TOGGLE_IS_MOBILE",payload:e.matches})},d=()=>{l({type:"TOGGLE_IS_KEYBOARD",payload:!0})},h=()=>{l({type:"TOGGLE_IS_KEYBOARD",payload:!1})};(0,e.useEffect)((()=>(window.matchMedia("(max-width: 640px)").addEventListener("change",i),window.addEventListener("keydown",d),window.addEventListener("pointerdown",h),()=>{window.removeEventListener("change",i),window.removeEventListener("keydown",d),window.removeEventListener("pointerdown",h)})),[]);const w=e=>{l({type:"SET_SDK",payload:e})},v=e=>{l({type:"SET_CHAT_VISIBILITY",payload:e})},b=e=>{l({type:"SET_CUSTOMER_ID",payload:e})},y=e=>{l({type:"SET_THREAD_ID",payload:e})},f=e=>{l({type:"SET_THREAD",payload:e})},p=e=>{l({type:"SET_SETTINGS",payload:e})},k=e=>{l({type:"SET_UNSEEN_COUNT",payload:e})},S=e=>{l({type:"SET_INSTIGATOR_ID",payload:e})},_=e=>{l({type:"SET_LIVE_REGION_TEXT",payload:e})},N=(0,e.useMemo)((()=>({...o,setSdk:w,setSettings:p,setCustomerId:b,setThreadId:y,setThread:f,setUnseenCount:k,setChatVisibility:v,setInstigatorId:S,setLiveRegionText:_})));return t().createElement(E.Provider,{value:N},n)},w=()=>(0,e.useContext)(E),v=(...e)=>e.filter((e=>e&&"string"==typeof e)).join(" "),{stripPageTitle:b}=a(792),y=()=>{const e=window.location.href.split("#")[0];document.title=b(document.title),window.history.pushState({history:!0},null,`${e}#webchat`)},f=()=>{if(window.history.state?.history)return window.history.back();document.title=b(document.title);const e=window.location.href.split("#")[0];return window.history.replaceState(null,null,e)},p=require("lodash.debounce");var k=a.n(p),S=a(168);const _=require("html-react-parser");var N=a.n(_);const T=/(?:www|https?)[^\s]+/gi,C=e=>(e.match(T)&&(e=e.replace(T,(e=>`<a class="govuk-link" href="${e}" target="_blank" rel="noreferrer">${e.replace(/https?:\/\//gi,"")}</a>`))),N()(e)),I=e=>({id:e.id,text:e.messageContent?.text,createdAt:new Date(e.createdAt),user:e.authorEndUserIdentity?.fullName?.trim()||null,assignee:e.authorUser?.firstName||null,direction:e.direction}),L=e=>{const t=S.DateTime.local();t.setZone("Europe/London");let a=`Floodline webchat transcript, ${t.toFormat("HH:mm:ss a, dd LLLL yyyy")}\n\n`;for(const t of e){const{text:e,direction:n,user:o,assignee:l,createdAt:r}=t,s="inbound"===n?o:`${l} (Floodline adviser)`;a+=`[${S.DateTime.fromJSDate(new Date(r)).setZone("Europe/London").toFormat("HH:mm:ss a, dd LLLL yyyy")}] ${s}: \n${e}\n\n`}return a=a.replace(/<a\b[^>]*>/i,"").replace(/<\/a>/i,""),encodeURIComponent(a)},A={SET_MESSAGE:(e,t)=>({...e,message:I(t),messages:[...e.messages,I(t)]}),SET_MESSAGES:(e,t)=>{return{...e,messages:(a=t,a.map((e=>I(e)))).reverse()};var a},SET_AGENT:(e,t)=>({...e,agent:t}),SET_AGENT_TYPING:(e,t)=>({...e,isAgentTyping:t}),SET_AGENT_STATUS:(e,t)=>({...e,agentStatus:t})},x={messages:[],agent:null,agentStatus:null,isAgentTyping:!1},D=(e,t)=>{const{type:a,payload:n}=t,o=A[a];return o?o.bind(void 0,e,n)():e},G=(0,e.createContext)(x),q=({sdk:a,playSound:n,onRecoverError:o,children:s})=>{const[c,i]=(0,e.useReducer)(D,x),{thread:u,threadId:d,setThread:m,setThreadId:g,setUnseenCount:E}=w(),h=e=>{i({type:"SET_AGENT",payload:e.detail.data.inboxAssignee}),i({type:"SET_AGENT_STATUS",payload:e.detail.data.contact.status}),E(e.detail.data.contact.customerStatistics.unseenMessagesCount)},v=e=>{i({type:"SET_AGENT",payload:e.detail.data.inboxAssignee}),i({type:"SET_AGENT_STATUS",payload:e.detail.data.case.status})},b=()=>{i({type:"SET_AGENT_TYPING",payload:!0})},y=()=>{i({type:"SET_AGENT_TYPING",payload:!1}),i({type:"SET_LIVE_REGION_TEXT"})},f=e=>{i({type:"SET_MESSAGE",payload:e.detail.data.message}),i({type:"SET_AGENT_STATUS",payload:e.detail.data.case.status}),E(e.detail.data.case.customerStatistics.unseenMessagesCount),JSON.parse(window.localStorage.getItem(r)).audio&&"outbound"===e.detail.data.message.direction&&n&&n()},p=e=>{i({type:"SET_AGENT_STATUS",payload:e.detail.data.case.status})};(0,e.useEffect)((()=>{a&&(a.onChatEvent(l.ChatEvent.LIVECHAT_RECOVERED,h),a.onChatEvent(l.ChatEvent.MESSAGE_CREATED,f),a.onChatEvent(l.ChatEvent.AGENT_TYPING_STARTED,b),a.onChatEvent(l.ChatEvent.AGENT_TYPING_ENDED,y),a.onChatEvent(l.ChatEvent.ASSIGNED_AGENT_CHANGED,v),a.onChatEvent(l.ChatEvent.CONTACT_STATUS_CHANGED,p))}),[a]);const k=async e=>{const t=await e.recover(),a=[];let n=t.messages;for(;n.length;){n.map((e=>a.push(e)));try{n=(await e.loadMoreMessages()).data.messages}catch(e){n=[]}}return a};(0,e.useEffect)((()=>{a&&d&&!u&&(console.log("recovering chat..."),(async()=>{try{await a.authorize();const e=await a.getThread(d),t=await k(e);m(e),S(t)}catch(e){console.log("[Chat Error] fetchThread",e),g(),m(),o()}})())}),[a,u,d]);const S=e=>{i({type:"SET_MESSAGES",payload:e})},_=(0,e.useMemo)((()=>({...c,sdk:a,fetchMessages:k,setMessages:S,onLiveChatRecovered:h,onAssignedAgentChanged:v,onAgentTypingStarted:b,onAgentTypingEnded:y,onMessageCreated:f,onContactStatusChanged:p})));return t().createElement(G.Provider,{value:_},s)},O=()=>(0,e.useContext)(G),M=()=>{const{liveRegionText:a,setLiveRegionText:n}=w(),{agentStatus:o}=O(),[l,r]=(0,e.useState)(),[s,c]=(0,e.useState)(),i="closed"===o||null===o,u=()=>{r(),c()},d=(0,e.useCallback)(k()((e=>{l?c(e):r(e)}),2e3),[l,s]);return(0,e.useEffect)((()=>(a&&(u(),d(a)),i&&(u(),n()),()=>{u(),n()})),[a]),t().createElement(t().Fragment,null,t().createElement("div",{className:"wc-live",role:"status","aria-atomic":"true"},l),t().createElement("div",{className:"wc-live",role:"status","aria-atomic":"true"},s))},{stripPageTitle:R}=a(792);function F(){const{availability:a,thread:n,isChatOpen:o,setChatVisibility:l,unseenCount:r,threadId:s,setUnseenCount:c,setInstigatorId:i,setLiveRegionText:u}=w(),d=(0,e.useRef)(),m=r>1?"new messages":"new message",g=r>0&&!o,E=R(document.title),h=e=>{e.preventDefault(),n?.lastMessageSeen(),c(0),l(!o),i(e.target.id),o?f():y()},b=e=>{" "===e.key&&e.preventDefault()},p=e=>{" "===e.key&&(n?.lastMessageSeen(),c(0),l(!o))};switch((0,e.useEffect)((()=>{g&&(document.title=`(${r} ${m}) - ${E}`)}),[r]),(0,e.useEffect)((()=>(g&&u(`Floodline webchat - ${r} ${m}`),()=>{u()})),[r,o]),(0,e.useEffect)((()=>{const e=()=>{if(!s)return;if("AVAILABLE"!==a)return;const e=d.current.parentElement.getBoundingClientRect().top+35>(window.innerHeight||document.documentElement.clientHeight),t=!o&&e;document.documentElement.classList.toggle("wc-u-scroll-padding",t),document.body.classList.toggle("wc-u-scroll-padding",t),d.current.classList.toggle("wc-availability--fixed",t)};return document.addEventListener("scroll",e),e(),()=>{document.removeEventListener("scroll",e)}}),[s,o,a]),a){case"EXISTING":case"UNAVAILABLE":return t().createElement("p",{className:"govuk-body"},"When it is available, a 'start chat' link will appear.");case"AVAILABLE":return t().createElement(t().Fragment,null,t().createElement("div",{className:v("wc-availability",o&&"wc-open"),ref:d},t().createElement("div",{className:"wc-availability__inner"},t().createElement("a",{id:"webchat-start-chat-link",className:"wc-availability__link",href:"#webchat",draggable:"false",onClick:h,onKeyUp:p,onKeyDown:b,role:"button","data-module":"govuk-button"},s?t().createElement(t().Fragment,null,"Show chat"):t().createElement(t().Fragment,null,"Start chat"),g?t().createElement("span",{className:"wc-availability__unseen"},r,t().createElement("span",{className:"govuk-visually-hidden"}," ",m)):null))),!o&&t().createElement(M,null));default:return t().createElement("p",{className:"govuk-body"},"Checking availability")}}const B=async e=>{const t=new(window.AudioContext||window.webkitAudioContext);if("suspended"===t.state){const e=["touchstart","touchend","mousedown","wheel","keydown","click"],a=n=>{e.forEach((e=>{document.body.removeEventListener(e,a)})),t.resume()};e.forEach((e=>{document.body.addEventListener(e,a,!1)}))}const a=await fetch(e),n=await a.arrayBuffer(),o=await t.decodeAudioData(n);return()=>{const e=t.createBufferSource();e.buffer=o,e.connect(t.destination),e.start()}},U=require("react-dom"),$=()=>{const{threadId:e,setInstigatorId:a}=w();if(!e)return null;const n=document.getElementById("webchat-skip-link-container");return n?t().createElement(t().Fragment,null,(0,U.createPortal)(t().createElement("a",{id:"webchat-skip-link",href:"#webchat",className:"govuk-skip-link","data-module":"govuk-skip-link",onClick:e=>{e.preventDefault(),a(e.target.id),window.location.hash="#webchat"},"data-wc-skiplink":!0,"data-wc-open-btn":!0},"Skip to webchat"),n)):null};function Y(){const{thread:e,threadId:a,setChatVisibility:n,setUnseenCount:o,isMobile:l}=w(),r=t=>{t.preventDefault(),n(!1),f(),a&&(e?.lastMessageSeen(),o(0))},s=t().createElement("button",{className:"wc-header__back","aria-label":"Close the webchat",onClick:r},t().createElement("svg",{"aria-hidden":"true",focusable:"false",width:"20",height:"20",viewBox:"0 0 20 20"},t().createElement("path",{d:"M4.828,11L12.314,18.485L10.899,19.899L1,10L10.899,0.101L12.314,1.515L4.828,9L19,9L19,11L4.828,11Z",fill:"currentColor"}))),c=t().createElement("button",{className:"wc-header__close","aria-label":"Close the webchat",onClick:r},t().createElement("svg",{"aria-hidden":"true",focusable:"false",width:"20",height:"20",viewBox:"0 0 20 20"},t().createElement("path",{d:"M10,8.6L15.6,3L17,4.4L11.4,10L17,15.6L15.6,17L10,11.4L4.4,17L3,15.6L8.6,10L3,4.4L4.4,3L10,8.6Z",fill:"currentColor"}))),i=t().createElement("button",{className:"wc-header__hide","aria-label":"Minimise the webchat",onClick:r},t().createElement("svg",{"aria-hidden":"true",focusable:"false",width:"20",height:"20",viewBox:"0 0 20 20"},t().createElement("path",{d:"M10 14.4l-7-7L4.4 6l5.6 5.6L15.6 6 17 7.4l-7 7z",fill:"currentColor"}))),u=l&&window.history.state,d=l&&!window.history.state;let m=c;return a&&(m=i,d&&(m=i)),!a&&d&&(m=c),u&&(m=null),t().createElement("div",{className:"wc-header"},u?s:null,t().createElement("h2",{id:"wc-header",className:"wc-header__title"},"Floodline webchat"),m)}function K({onContinue:e}){return t().createElement(t().Fragment,null,t().createElement(Y,null),t().createElement("div",{className:"wc-body"},t().createElement("div",{className:"wc-content"},t().createElement("h3",{id:"wc-subtitle",className:"wc-heading","aria-live":"polite"},"What you can use webchat for"),t().createElement("p",null,"Webchat lets you talk directly to a Floodline adviser."),t().createElement("p",null,"You can use webchat to get:"),t().createElement("ul",{className:"wc-list"},t().createElement("li",null,"current flood warnings and alerts in your area"),t().createElement("li",null,"information on the flood warning service"),t().createElement("li",null,"advice on what to do before, during and after a flood")),t().createElement("p",null,"There are other ways to ",t().createElement("a",{className:"govuk-link",href:"https://www.gov.uk/sign-up-for-flood-warnings",target:"_blank",rel:"noreferrer"},"sign up for flood warnings")," and ",t().createElement("a",{className:"govuk-link",href:"https://www.fws.environment-agency.gov.uk/app/olr/login",target:"_blank",rel:"noreferrer"},"manage your flood warnings account"),"."),t().createElement("p",null,"Do not use webchat to ",t().createElement("a",{className:"govuk-link",href:"https://www.gov.uk/report-flood-cause",target:"_blank",rel:"noreferrer"},"report a flood"),"."),t().createElement("button",{className:"govuk-button wc-button govuk-!-margin-top-1","data-module":"govuk-button",onClick:e},"Continue"),t().createElement("h3",{className:"wc-heading"},"Other flood information"),t().createElement("p",null,"Call Floodline for all other flood and flood warning information."),t().createElement("p",null,t().createElement("strong",null,"Floodline helpline"),t().createElement("br",null),"Telephone: 0345 988 1188",t().createElement("br",null),"Textphone: 0345 602 6340",t().createElement("br",null),"Open 24 hours a day, 7 days a week",t().createElement("br",null),t().createElement("a",{className:"govuk-link",href:"https://gov.uk/call-charges",target:"_blank",rel:"noreferrer"},"Find out more about call charges")))))}const V=require("uuid"),P=({errors:e})=>{const a=Object.keys(e),n=e=>{e.preventDefault();const t=e.target.getAttribute("data-key");document.querySelector(`#wc-${t}`).focus()};return 0===a.length?null:t().createElement("div",{className:"govuk-error-summary govuk-!-static-margin-bottom-7","data-module":"govuk-error-summary",tabIndex:"-1"},t().createElement("div",{role:"alert"},t().createElement("h2",{id:"wc-error",className:"wc-error-summary__title govuk-error-summary__title"},"There is a problem"),t().createElement("div",{className:"govuk-error-summary__body"},t().createElement("ul",{className:"govuk-list govuk-error-summary__list wc-error-summary__list"},a.map((a=>t().createElement("li",{key:a},t().createElement("a",{href:"#","data-key":a,onClick:n},e[a]))))))))},H=500;function j({initSdk:a,onPreChatScreen:n}){const{setSdk:o,setCustomerId:l,setThreadId:r,setThread:s,setLiveRegionText:c}=w(),[i,u]=(0,e.useState)({}),[d,m]=(0,e.useState)(0),[g,E]=(0,e.useState)(!1),h=(0,e.useRef)(),b=(0,e.useRef)(),y=H>=d;let f=`You have ${H-d} characters remaining`;y||(f=`You have ${d-H} characters too many`),(0,e.useEffect)((()=>{Object.keys(i).length&&document.querySelector(".govuk-error-summary")?.focus()}),[i]);const p=g?"Requesting...":"Request chat";return(0,e.useEffect)((()=>{g&&c(p)}),[g]),t().createElement(t().Fragment,null,t().createElement(Y,null),t().createElement("div",{className:"wc-body"},t().createElement("div",{className:"wc-content"},t().createElement("a",{href:"#",className:"wc-back-link govuk-back-link",onClick:n},"What you can use webchat for"),t().createElement(P,{errors:i}),t().createElement("h3",{id:"wc-subtitle",className:"wc-heading","aria-live":"polite"},"Your name and question"),t().createElement("form",null,t().createElement("div",{className:v("wc-form-group","govuk-form-group",i.name&&"govuk-form-group--error")},t().createElement("label",{className:"wc-label govuk-label",htmlFor:"wc-name"},"Your name"),i.name&&t().createElement("p",{className:"govuk-error-message"},t().createElement("span",{className:"govuk-visually-hidden"},"Error:")," ",i.name),t().createElement("input",{ref:h,className:v("wc-input","govuk-input",i.name&&"govuk-input--error"),id:"wc-name",name:"name",type:"text","data-testid":"request-chat-user-name"})),t().createElement("div",{className:"wc-form-group govuk-character-count","data-module":"govuk-character-count","data-maxlength":"500"},t().createElement("div",{className:v("govuk-form-group",i.question&&"govuk-form-group--error")},t().createElement("label",{className:"wc-label govuk-label",htmlFor:"wc-question"},"Your question"),i.question&&t().createElement("p",{className:"govuk-error-message"},t().createElement("span",{className:"govuk-visually-hidden"},"Error:"),i.question),t().createElement("textarea",{ref:b,id:"wc-question",name:"question",rows:"5","aria-describedby":"wc-question-info",onChange:e=>{m(e.target.value.length)},className:v("wc-textarea","govuk-textarea","govuk-js-character-count",!y||i.question?"govuk-textarea--error":""),"data-testid":"request-chat-user-question"}),t().createElement("div",{id:"wc-question-info",className:"wc-hint govuk-hint govuk-char-count__msg",style:{color:y?"":"#d4351c"},"aria-hidden":"true"},f),t().createElement("div",{className:"govuk-character-count__sr-status govuk-visually-hidden","aria-live":"polite"},f))),t().createElement("div",{className:"wc-inset-text govuk-inset-text"},"By selecting 'Request chat' you agree to the terms of our ",t().createElement("a",{href:"https://check-for-flooding.service.gov.uk/privacy-notice",target:"_blank",rel:"noreferrer",className:"govuk-link"},"privacy notice"),"."),t().createElement("button",{className:"wc-button govuk-button govuk-!-margin-top-1","data-module":"govuk-button",onClick:async e=>{if(e.preventDefault(),g)return;const t={};if(0===h.current.value.length&&(t.name="Enter your name"),0===b.current.value.length&&(t.question="Enter your question"),b.current.value.length>H&&(t.question="Your question must be 500 characters or less"),0===Object.keys(t).length)try{E(!0);const e=V.v4(),t=a(),n=await t.authorize(),c=n?.consumerIdentity.idOnExternalPlatform,i=await t.getThread(e);i.setCustomField("threadid",e),await t.getCustomer().setName(h.current.value),await i.startChat(b.current.value||"Begin conversation"),o(t),l(c),r(e),s(i)}catch(e){console.log("[Request chat Error]",e)}u(t)},"aria-disabled":g},p)))))}function W({children:e}){return t().createElement("div",{className:"wc-footer"},e)}function J({message:e,previousMessage:a}){const n="outbound"===e.direction,o=e?.direction===a?.direction;return t().createElement("li",{className:v("wc-chat__message",n?"outbound":"inbound")},t().createElement("div",{className:"wc-chat__from"},o?null:t().createElement("span",{className:v(n?"outbound":"inbound")},n?e.assignee:"You"),t().createElement("span",{className:"govuk-visually-hidden"},":")),t().createElement("div",{className:v("wc-chat__text",n?"outbound":"inbound")},C(e.text)))}const Z=(t,a)=>{(0,e.useEffect)((()=>{if(t){t.style.height="0px";const e=t.scrollHeight;t.style.height=`${e}px`}}),[t,a])},X=(e,t,a)=>{if("UNAVAILABLE"===e)return"Webchat is not currently available";if(!t)return"Connecting to Floodline";switch(t){case"closed":case"resolved":return a?`${a} ended the session`:"Session ended by advisor";default:return a?`You are speaking with ${a}`:"Waiting for an adviser"}};function z({onEndChatScreen:a,onSettingsScreen:n}){const{availability:o,thread:l,isChatOpen:r,settings:s,isKeyboard:c,setLiveRegionText:u}=w(),{messages:d,agent:m,agentStatus:g,isAgentTyping:E}=O(),[h,v]=(0,e.useState)(""),[b,y]=(0,e.useState)(),[f,p]=(0,e.useState)(),[S,_]=(0,e.useState)(!1),N=(0,e.useRef)();Z(N.current,h),(0,e.useEffect)((()=>{if(s.scroll&&0!==d.length){const e=document.querySelector(".wc-body");e.scrollTop=e.scrollHeight}}),[d,E]),(0,e.useEffect)((()=>{const e=document.querySelector(".wc-form__label");0===h.length?e.classList.remove("govuk-visually-hidden"):e.classList.add("govuk-visually-hidden")}),[h]),(0,e.useEffect)((()=>{y(m?.nickname||m?.firstName),p(X(o,g,b))}),[m,b,g]),(0,e.useEffect)((()=>(f&&r&&u(`Floodline webchat - ${f}`),()=>{u()})),[f,r]),(0,e.useEffect)((()=>(E&&r&&u(`${b} is typing...`),()=>{u()})),[E,r]),(0,e.useEffect)((()=>{const e=d[d.length-1];return"closed"!==g&&"outbound"===e?.direction&&r&&u(`${b} said: ${e.text}`),()=>{u()}}),[d,r]);const T=()=>{if(0!==N.current.value.length&&"closed"!==g){try{const e=N.current.value.trim();l.sendTextMessage(e),u(`You said: ${e}`)}catch(e){console.log("[Chat Error] sendMessage",e)}v("")}},C=()=>{const e=L(d);document.querySelector("#transcript-download").setAttribute("href",`data:text/plain;charset=utf-8,${e}`)},I=(0,e.useCallback)(k()((()=>{l.keystroke(),setTimeout((()=>{l.stopTyping()}),i)}),100),[l]),A=e=>{if("Enter"!==e.key||e.shiftKey)" "===e.key?("end-chat"===e.target.id&&a(e),"wc-settings"===e.target.id&&n(e)):I();else switch(e.target.id){case"text-area":e.preventDefault(),T();break;case"end-chat":a(e);break;case"wc-settings":n(e);break;case"transcript-download":C()}};return t().createElement(t().Fragment,null,t().createElement(Y,null),t().createElement("div",{className:"wc-status"},t().createElement("p",{className:"wc-status__availability"},f),l&&t().createElement("a",{id:"end-chat",className:"wc-status__link",href:"#","data-module":"govuk-button",role:"button",onClick:a,onKeyDown:A},"End chat")),t().createElement("div",{className:"wc-body",tabIndex:"0"},t().createElement("ul",{className:"wc-chat"},d.length?d.map(((e,a)=>t().createElement(J,{key:e.id,message:e,previousMessage:d[a-1]}))):null,E?t().createElement("li",{className:"wc-chat__message outbound"},t().createElement("div",{className:"wc-chat__from"},b," is typing"),t().createElement("div",{className:"wc-chat__text outbound"},t().createElement("svg",{width:"28",height:"16",x:"0px",y:"0px",viewBox:"0 0 28 16"},t().createElement("circle",{stroke:"none",cx:"3",cy:"8",r:"3",fill:"currentColor"}),t().createElement("circle",{stroke:"none",cx:"14",cy:"8",r:"3",fill:"currentColor"}),t().createElement("circle",{stroke:"none",cx:"25",cy:"8",r:"3",fill:"currentColor"})))):null)),t().createElement(W,null,t().createElement("form",{className:"wc-form"+(S?" wc-focus-within":""),noValidate:!0,onSubmit:e=>{e.preventDefault(),T()}},t().createElement("label",{className:"govuk-label wc-form__label",htmlFor:"wc-form-textarea"},"Your message",t().createElement("span",{className:"govuk-visually-hidden"}," (enter key submits)")),t().createElement("textarea",{ref:N,rows:"1","aria-required":"true",className:"wc-form__textarea",id:"text-area",name:"message",onChange:e=>{v(e.target?.value)},onKeyDown:A,onFocus:()=>{_(c)},onBlur:()=>{_(!1)},value:h}),t().createElement("input",{type:"submit",className:"wc-form__button govuk-button",value:"Send","data-prevent-double-click":"true"})),t().createElement("div",{className:"wc-footer__settings"},t().createElement("a",{href:"#",id:"wc-settings",className:"wc-footer__settings-link","data-module":"govuk-button",onKeyDown:A,onClick:n},"Settings"),t().createElement("a",{href:"#",id:"transcript-download",className:"wc-footer__settings-link","data-module":"govuk-button",download:"floodline-webchat-transcript.txt",onKeyDown:A,onClick:C},"Save chat"))))}function Q(){return t().createElement(t().Fragment,null,t().createElement(Y,null),t().createElement("div",{className:"wc-body"},t().createElement("div",{className:"wc-content"},t().createElement("h3",{id:"wc-subtitle",className:"govuk-heading-m"},"Webchat is currently not available"),t().createElement("p",{className:"govuk-body-s"},"Try again later, or call Floodline:"),t().createElement("p",{className:"govuk-body-s"},t().createElement("strong",null,"Floodline helpline"),t().createElement("br",null),"Telephone: 0345 988 1188",t().createElement("br",null),"Textphone: 0345 602 6340",t().createElement("br",null),"Open 24 hours a day, 7 days a week",t().createElement("br",null),t().createElement("a",{className:"govuk-link",href:"https://gov.uk/call-charges"},"Find out more about call charges")),t().createElement("p",{className:"govuk-body-s"},"We're running webchat as a trial, it will not always be available."))))}function ee({onChatScreen:a,onEndChatConfirm:n}){const{thread:o,setSdk:l,setCustomerId:r,setThreadId:s,threadId:c,setUnseenCount:i,isKeyboard:u}=w(),{agentStatus:d,setMessages:m}=O(),g=async e=>{e.preventDefault(),window.localStorage.setItem("tmpThreadId",c),o?.lastMessageSeen(),l(),s(),m([]),r(),i(0),"closed"!==d&&o.endChat(),n(e)};(0,e.useEffect)((()=>{u&&setTimeout((()=>{document.querySelector("#confirm-endchat").focus()}),10)}),[]);const E=e=>{"Enter"!==e.key&&" "!==e.key||"confirm-endchat"!==e.target.id||g(e),"Enter"!==e.key&&" "!==e.key||"resume-chat"!==e.target.id||a(e)};return t().createElement(t().Fragment,null,t().createElement(Y,null),t().createElement("div",{className:"wc-body"},t().createElement("div",{className:"wc-content"},t().createElement("h3",{id:"wc-subtitle",className:"wc-heading","aria-live":"polite"},"Are you sure you want to end the chat?"),t().createElement("div",{className:"govuk-button-group"},t().createElement("a",{id:"confirm-endchat",href:"#endChat",role:"button",className:"wc-button govuk-button","data-module":"govuk-button",onClick:g,onKeyDown:E},"Yes, end chat"),t().createElement("a",{id:"resume-chat",href:"#resumeChat",role:"button",className:"wc-link govuk-link","data-module":"govuk-button",onClick:a,onKeyDown:E},"No, resume chat")))))}function te({onCancel:a}){const{settings:n,setSettings:o}=w(),[l,r]=(0,e.useState)(n.audio),[s,c]=(0,e.useState)(n.scroll),i=e=>{e.preventDefault(),o({audio:l,scroll:s}),a(e)},u=e=>{"Enter"!==e.key&&" "!==e.key||"settings-save"!==e.target.id?"Enter"!==e.key&&" "!==e.key||"settings-cancel"!==e.target.id||a(e):i(e)};return t().createElement(t().Fragment,null,t().createElement(Y,null),t().createElement("div",{className:"wc-body"},t().createElement("div",{className:"wc-content"},t().createElement("fieldset",{className:"govuk-fieldset govuk-!-margin-bottom-4"},t().createElement("legend",{className:"govuk-fieldset__legend govuk-fieldset__legend"},t().createElement("h3",{id:"wc-subtitle",className:"wc-heading"},"Change settings")),t().createElement("div",{className:"govuk-checkboxes govuk-checkboxes--small","data-module":"govuk-checkboxes"},t().createElement("div",{className:"govuk-checkboxes__item"},t().createElement("input",{id:"audio",name:"audio",type:"checkbox",value:"audio",className:"govuk-checkboxes__input",defaultChecked:l,onChange:()=>r(!l)}),t().createElement("label",{className:"wc-label govuk-label govuk-checkboxes__label",htmlFor:"audio"},"Play a sound when receiving a new message")),t().createElement("div",{className:"govuk-checkboxes__item"},t().createElement("input",{id:"scroll",name:"scroll",type:"checkbox",value:"scroll",className:"govuk-checkboxes__input",defaultChecked:s,onChange:()=>c(!s)}),t().createElement("label",{className:"wc-label govuk-label govuk-checkboxes__label",htmlFor:"scroll"},"Scroll automatically to a new message")))),t().createElement("div",{className:"govuk-button-group"},t().createElement("a",{id:"settings-save",href:"#",className:"wc-button govuk-button","data-module":"govuk-button",role:"button",onClick:i,onKeyDown:u},"Save"),t().createElement("a",{id:"settings-cancel",href:"#",className:"wc-link govuk-link","data-module":"govuk-button",role:"button",onClick:a,onKeyDown:u},"Cancel")))))}function ae({onCancel:e}){const a=()=>{const e=window.localStorage.getItem("tmpThreadId");window.location.href=`https://defragroup.eu.qualtrics.com/jfe/form/SV_8dgFSJcxxIfqx5Y?Id=${e}&Source=${window.location.href}`,window.localStorage.removeItem("tmpThreadId")},n=async t=>{window.localStorage.removeItem("tmpThreadId"),e(t)},o=e=>{"Enter"!==e.key&&" "!==e.key||("feedback-close"===e.target.id&&n(e),"feedback-send"===e.target.id&&a())};return t().createElement(t().Fragment,null,t().createElement(Y,null),t().createElement("div",{className:"wc-body"},t().createElement("div",{className:"wc-content"},t().createElement("h3",{id:"wc-subtitle",className:"wc-heading"},"Give feedback on Floodline webchat"),t().createElement("p",null,"We're running webchat as a trial. you can ",t().createElement("a",{id:"feedback-send",className:"govuk-link",href:"#",target:"_blank",rel:"noreferrer",onKeyDown:o,onClick:a},"give feedback")," to help us improve it."),t().createElement("p",null,t().createElement("a",{id:"feedback-close",className:"wc-link govuk-link",href:"#","data-module":"govuk-button",role:"button",onKeyDown:o,onClick:n},"Close")))))}const ne="aria-hidden",oe="data-wc-inert",le=e=>{for(const t of document.body.children)"wc-panel"!==t.id&&(e&&!t.getAttribute(ne)?(t.setAttribute(ne,"true"),t.setAttribute(oe,"")):t.hasAttribute(oe)&&(t.removeAttribute(ne),t.removeAttribute(oe)))},re=(t,a)=>{const[n,o]=(0,e.useState)([]),l=(0,e.useCallback)((e=>{const t=document.querySelector("#wc-panel");"Tab"===e.key&&(t&&!document.activeElement.closest("#wc-panel")&&t.focus(),e.shiftKey?(document.activeElement===n[0]||document.activeElement===document.querySelector("#wc-panel"))&&(n[n.length-1].focus(),e.preventDefault()):document.activeElement===n[n.length-1]&&(n[0].focus(),e.preventDefault()))}),[n]);(0,e.useEffect)((()=>{o((()=>{const e=document.body.querySelectorAll(["#wc-panel a:not([disabled])","#wc-panel button:not([disabled])","#wc-panel select:not([disabled])","#wc-panel input:not([disabled])","#wc-panel textarea:not([disabled])",'#wc-panel *[tabindex="0"]:not([disabled])'].join(","));return Array.from(e).filter((e=>!e.closest("[hidden]")&&!e.closest('[aria-hidden="true"]')))})())}),[t]),(0,e.useEffect)((()=>(a&&(le(!0),document.querySelector("#wc-panel").focus(),document.addEventListener("keydown",l)),()=>{le(),document.removeEventListener("keydown",l)})),[n,a])};function se({initSdk:a,playSound:n}){const{sdk:o,thread:l,availability:r,instigatorId:s,threadId:c,setSdk:i,setChatVisibility:u,setUnseenCount:d,isMobile:m,isKeyboard:g,isChatOpen:E}=w(),[h,b]=(0,e.useState)(c?2:0);re(h,E);const y=(0,e.useCallback)((e=>{"Escape"!==e.key&&"Esc"!==e.key||(c&&(l?.lastMessageSeen(),d(0)),u(!1),f())}),[l,c,d,u]);(0,e.useEffect)((()=>{E||document.getElementById(s)?.focus()}),[E]),(0,e.useEffect)((()=>(document.body.classList.remove("wc-u-hidden"),document.getElementsByTagName("html")[0].classList.add("wc-u-html"),document.body.classList.add("wc-u-body"),()=>{document.getElementsByTagName("html")[0].classList.remove("wc-u-html"),document.body.classList.remove("wc-u-body")})),[m]),(0,e.useEffect)((()=>(document.addEventListener("keydown",y),()=>{document.removeEventListener("keydown",y)})),[y,u]),(0,e.useEffect)((()=>{c&&(l||i(a()),b(2))}),[l,c]);const p=e=>t=>{t.preventDefault(),b(e)},k=p(0),S=p(1),_=p(2),N=p(3),T=p(4),C=p(5);let I;switch(h){case 0:default:I=t().createElement(K,{onContinue:S});break;case 1:I=t().createElement(j,{initSdk:a,onPreChatScreen:k});break;case 2:I=t().createElement(q,{sdk:o,playSound:n,onRecoverError:()=>b(0)},t().createElement(z,{onSettingsScreen:C,onEndChatScreen:N}));break;case 3:I=t().createElement(q,{sdk:o,playSound:n},t().createElement(ee,{onChatScreen:_,onEndChatConfirm:T}));break;case 4:I=t().createElement(ae,{onCancel:()=>{u(!1),f(),b(0)}});break;case 5:I=t().createElement(q,{sdk:o,playSound:n},t().createElement(te,{onCancel:_}))}"UNAVAILABLE"===r&&(I=t().createElement(Q,null));const L=t().createElement("div",{id:"wc-panel",role:"dialog",style:{display:E?"flex":"none"},className:v("wc-panel",g&&"wc-focus-visible"),tabIndex:"-1","aria-modal":"true","aria-labelledby":"wc-header wc-subtitle",open:E},t().createElement("div",{className:"wc-panel__inner"},I),t().createElement(M,null));return t().createElement(t().Fragment,null,(0,U.createPortal)(L,document.body))}async function ce(e,a){const n=(0,o.createRoot)(e);let r,c;try{const e=await async function(e){const t=await fetch(e);return{availability:(await t.json()).availability||"UNAVAILABLE"}}(a.availabilityEndpoint);c=await B(a.audioUrl),r=e.availability}catch(e){r="UNAVAILABLE"}n.render(t().createElement(h,{availability:r},t().createElement(F,null),t().createElement($,null),t().createElement(se,{initSdk:()=>new l.ChatSdk({brandId:a.brandId,channelId:a.channelId,customerId:window.localStorage.getItem(s)||"",environment:a.environment,onError:e=>{console.log("ChatSdk onError",e)}}),playSound:c})))}})(),module.exports=n})();
1
+ (()=>{var e={792:(e,t,a)=>{const{DateTime:n}=a(168),o=e=>Number(e.split(":")[0]);e.exports={isWithinHours:(e,t)=>{const a=t?n.fromISO(t):n.local();a.setZone("Europe/London");const l=t?new Date(t):new Date,r=l.toLocaleDateString("en-GB",{weekday:"long"}),s=l.toLocaleDateString("en-GB").split("/"),c=e.find((e=>e.day===r)),i=n.local(Number(s[2]),Number(s[1]),Number(s[0]),o(c.openTime)),u=n.local(Number(s[2]),Number(s[1]),Number(s[0]),o(c.closeTime));return a.diff(i).milliseconds>=0&&a.diff(u).milliseconds<=0},stripPageTitle:e=>e.replace(/^\(\d+ new messages?\) - /,"")}},168:e=>{"use strict";e.exports=require("luxon")}},t={};function a(n){var o=t[n];if(void 0!==o)return o.exports;var l=t[n]={exports:{}};return e[n](l,l.exports,a),l.exports}a.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return a.d(t,{a:t}),t},a.d=(e,t)=>{for(var n in t)a.o(t,n)&&!a.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),a.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var n={};(()=>{"use strict";a.r(n),a.d(n,{init:()=>ne});const e=require("react");var t=a.n(e);const o=require("react-dom/client"),l=require("@nice-devone/nice-cxone-chat-web-sdk"),r=(...e)=>e.filter((e=>e&&"string"==typeof e)).join(" "),s=require("react-dom");var c=a(168);const i=require("html-react-parser");var u=a.n(i);const d=/(?:www|https?)[^\s]+/gi,m=e=>(e.match(d)&&(e=e.replace(d,(e=>`<a class="govuk-link" href="${e}" target="_blank" rel="noreferrer">${e.replace(/https?:\/\//gi,"")}</a>`))),u()(e)),g=e=>({id:e.id,text:e.messageContent?.text,createdAt:new Date(e.createdAt),user:e.authorEndUserIdentity?.fullName?.trim()||null,assignee:e.authorUser?.firstName||null,direction:e.direction}),h=e=>{const t=c.DateTime.local();t.setZone("Europe/London");let a=`Floodline webchat transcript, ${t.toFormat("HH:mm:ss a, dd LLLL yyyy")}\n\n`;for(const t of e){const{text:e,direction:n,user:o,assignee:l,createdAt:r}=t,s="inbound"===n?o:`${l} (Floodline adviser)`;a+=`[${c.DateTime.fromJSDate(new Date(r)).setZone("Europe/London").toFormat("HH:mm:ss a, dd LLLL yyyy")}] ${s}: \n${e}\n\n`}return a=a.replace(/<a\b[^>]*>/i,"").replace(/<\/a>/i,""),encodeURIComponent(a)},E="webchat_settings",w="webchat_customer_id",v="webchat_thread_id",b=4e3,y="message_unseen_count",f={SET_CHAT_VISIBILITY:(e,t)=>({...e,isChatOpen:t}),SET_AVAILABILITY:(e,t)=>({...e,availability:t}),SET_SETTINGS:(e,t)=>(t?window.localStorage.setItem(E,JSON.stringify(t)):window.localStorage.removeItem(E),{...e,settings:t}),SET_CUSTOMER_ID:(e,t)=>(t?window.localStorage.setItem(w,t):window.localStorage.removeItem(w),{...e,customerId:t}),SET_THREAD_ID:(e,t)=>(t?window.localStorage.setItem(v,t):window.localStorage.removeItem(v),{...e,threadId:t}),SET_THREAD:(e,t)=>({...e,thread:t}),SET_MESSAGE:(e,t)=>({...e,message:g(t),messages:[...e.messages,g(t)]}),SET_MESSAGES:(e,t)=>{return{...e,messages:(a=t,a.map((e=>g(e)))).reverse()};var a},SET_AGENT:(e,t)=>({...e,agent:t}),SET_AGENT_TYPING:(e,t)=>({...e,isAgentTyping:t}),SET_AGENT_STATUS:(e,t)=>({...e,agentStatus:t}),SET_UNSEEN_COUNT:(e,t)=>(window.localStorage.setItem(y,t),{...e,unseenCount:t}),SET_INSTIGATOR_ID:(e,t)=>({...e,instigatorId:t}),SET_LIVE_REGION_TEXT:(e,t)=>({...e,liveRegionText:t}),TOGGLE_IS_MOBILE:(e,t)=>({...e,isMobile:t}),TOGGLE_IS_KEYBOARD:(e,t)=>({...e,isKeyboard:t})},p={availability:null,customerId:null,threadId:null,thread:null,messages:[],unseenCount:0,instigatorId:null,agent:null,agentStatus:null,isAgentTyping:!1,isChatOpen:!1,isMobile:window.matchMedia("(max-width: 640px)").matches,isKeyboard:!1,settings:{audio:!0,scroll:!0}},k=(e,t)=>{const{type:a,payload:n}=t,o=f[a];return o?o.bind(void 0,e,n)():e},S=(0,e.createContext)(p),_=({sdk:a,availability:n,playSound:o,children:r})=>{const[s,c]=(0,e.useReducer)(k,p),i=e=>{c({type:"SET_AGENT",payload:e.detail.data.inboxAssignee}),c({type:"SET_AGENT_STATUS",payload:e.detail.data.contact.status}),c({type:"SET_UNSEEN_COUNT",payload:e.detail.data.contact.customerStatistics.unseenMessagesCount})},u=e=>{c({type:"SET_AGENT",payload:e.detail.data.inboxAssignee}),c({type:"SET_AGENT_STATUS",payload:e.detail.data.case.status})},d=()=>{c({type:"SET_AGENT_TYPING",payload:!0})},m=()=>{c({type:"SET_AGENT_TYPING",payload:!1}),c({type:"SET_LIVE_REGION_TEXT"})},g=e=>{c({type:"SET_MESSAGE",payload:e.detail.data.message}),c({type:"SET_AGENT_STATUS",payload:e.detail.data.case.status}),c({type:"SET_UNSEEN_COUNT",payload:e.detail.data.case.customerStatistics.unseenMessagesCount}),JSON.parse(window.localStorage.getItem(E)).audio&&"outbound"===e.detail.data.message.direction&&o&&o()},h=e=>{c({type:"SET_AGENT_STATUS",payload:e.detail.data.case.status})},b=e=>{c({type:"TOGGLE_IS_MOBILE",payload:e.matches})},f=()=>{c({type:"TOGGLE_IS_KEYBOARD",payload:!0})},_=()=>{c({type:"TOGGLE_IS_KEYBOARD",payload:!1})};(0,e.useEffect)((()=>(a.onChatEvent(l.ChatEvent.LIVECHAT_RECOVERED,i),a.onChatEvent(l.ChatEvent.MESSAGE_CREATED,g),a.onChatEvent(l.ChatEvent.AGENT_TYPING_STARTED,d),a.onChatEvent(l.ChatEvent.AGENT_TYPING_ENDED,m),a.onChatEvent(l.ChatEvent.ASSIGNED_AGENT_CHANGED,u),a.onChatEvent(l.ChatEvent.CONTACT_STATUS_CHANGED,h),window.matchMedia("(max-width: 640px)").addEventListener("change",b),window.addEventListener("keydown",f),window.addEventListener("pointerdown",_),()=>{window.removeEventListener("change",b),window.removeEventListener("keydown",f),window.removeEventListener("pointerdown",_)})),[a]),(0,e.useEffect)((()=>{c({type:"SET_AVAILABILITY",payload:n}),T(window.localStorage.getItem(w)),C(window.localStorage.getItem(v)),A(JSON.parse(window.localStorage.getItem(E))||s.settings),x(window.localStorage.getItem(y))}),[]),(0,e.useEffect)((()=>{"#webchat"===window.location.hash&&N(!0);const e=()=>{"#webchat"===window.location.hash?N(!0):N(!1)};return window.addEventListener("popstate",e),()=>{window.removeEventListener("popstate",e)}}),[]);const N=e=>{c({type:"SET_CHAT_VISIBILITY",payload:e})},T=e=>{c({type:"SET_CUSTOMER_ID",payload:e})},C=e=>{c({type:"SET_THREAD_ID",payload:e})},I=e=>{c({type:"SET_THREAD",payload:e})},L=e=>{c({type:"SET_MESSAGES",payload:e})},A=e=>{c({type:"SET_SETTINGS",payload:e})},x=e=>{c({type:"SET_UNSEEN_COUNT",payload:e})},D=e=>{c({type:"SET_INSTIGATOR_ID",payload:e})},G=e=>{c({type:"SET_LIVE_REGION_TEXT",payload:e})},q=(0,e.useMemo)((()=>({...s,sdk:a,setSettings:A,setCustomerId:T,setThreadId:C,setThread:I,setMessages:L,setUnseenCount:x,setChatVisibility:N,setInstigatorId:D,setLiveRegionText:G,onLiveChatRecovered:i,onAssignedAgentChanged:u,onAgentTypingStarted:d,onAgentTypingEnded:m,onMessageCreated:g,onContactStatusChanged:h})));return t().createElement(S.Provider,{value:q},r)},N=()=>(0,e.useContext)(S),{stripPageTitle:T}=a(792),C=()=>{const e=window.location.href.split("#")[0];document.title=T(document.title),window.history.pushState({history:!0},null,`${e}#webchat`)},I=()=>{if(window.history.state?.history)return window.history.back();document.title=T(document.title);const e=window.location.href.split("#")[0];return window.history.replaceState(null,null,e)};function L(){const{thread:e,threadId:a,setChatVisibility:n,setUnseenCount:o,isMobile:l}=N(),r=t=>{t.preventDefault(),n(!1),I(),a&&(e?.lastMessageSeen(),o(0))},s=t().createElement("button",{className:"wc-header__back","aria-label":"Close the webchat",onClick:r},t().createElement("svg",{"aria-hidden":"true",focusable:"false",width:"20",height:"20",viewBox:"0 0 20 20"},t().createElement("path",{d:"M4.828,11L12.314,18.485L10.899,19.899L1,10L10.899,0.101L12.314,1.515L4.828,9L19,9L19,11L4.828,11Z",fill:"currentColor"}))),c=t().createElement("button",{className:"wc-header__close","aria-label":"Close the webchat",onClick:r},t().createElement("svg",{"aria-hidden":"true",focusable:"false",width:"20",height:"20",viewBox:"0 0 20 20"},t().createElement("path",{d:"M10,8.6L15.6,3L17,4.4L11.4,10L17,15.6L15.6,17L10,11.4L4.4,17L3,15.6L8.6,10L3,4.4L4.4,3L10,8.6Z",fill:"currentColor"}))),i=t().createElement("button",{className:"wc-header__hide","aria-label":"Minimise the webchat",onClick:r},t().createElement("svg",{"aria-hidden":"true",focusable:"false",width:"20",height:"20",viewBox:"0 0 20 20"},t().createElement("path",{d:"M10 14.4l-7-7L4.4 6l5.6 5.6L15.6 6 17 7.4l-7 7z",fill:"currentColor"}))),u=l&&window.history.state,d=l&&!window.history.state;let m=c;return a&&(m=i,d&&(m=i)),!a&&d&&(m=c),u&&(m=null),t().createElement("div",{className:"wc-header"},u?s:null,t().createElement("h2",{id:"wc-header",className:"wc-header__title"},"Floodline webchat"),m)}function A({onContinue:e}){return t().createElement(t().Fragment,null,t().createElement(L,null),t().createElement("div",{className:"wc-body"},t().createElement("div",{className:"wc-content"},t().createElement("h3",{id:"wc-subtitle",className:"wc-heading","aria-live":"polite"},"What you can use webchat for"),t().createElement("p",null,"Webchat lets you talk directly to a Floodline adviser."),t().createElement("p",null,"You can use webchat to get:"),t().createElement("ul",{className:"wc-list"},t().createElement("li",null,"current flood warnings and alerts in your area"),t().createElement("li",null,"information on the flood warning service"),t().createElement("li",null,"advice on what to do before, during and after a flood")),t().createElement("p",null,"There are other ways to ",t().createElement("a",{className:"govuk-link",href:"https://www.gov.uk/sign-up-for-flood-warnings",target:"_blank",rel:"noreferrer"},"sign up for flood warnings")," and ",t().createElement("a",{className:"govuk-link",href:"https://www.fws.environment-agency.gov.uk/app/olr/login",target:"_blank",rel:"noreferrer"},"manage your flood warnings account"),"."),t().createElement("p",null,"Do not use webchat to ",t().createElement("a",{className:"govuk-link",href:"https://www.gov.uk/report-flood-cause",target:"_blank",rel:"noreferrer"},"report a flood"),"."),t().createElement("button",{className:"govuk-button wc-button govuk-!-margin-top-1","data-module":"govuk-button",onClick:e},"Continue"),t().createElement("h3",{className:"wc-heading"},"Other flood information"),t().createElement("p",null,"Call Floodline for all other flood and flood warning information."),t().createElement("p",null,t().createElement("strong",null,"Floodline helpline"),t().createElement("br",null),"Telephone: 0345 988 1188",t().createElement("br",null),"Textphone: 0345 602 6340",t().createElement("br",null),"Open 24 hours a day, 7 days a week",t().createElement("br",null),t().createElement("a",{className:"govuk-link",href:"https://gov.uk/call-charges",target:"_blank",rel:"noreferrer"},"Find out more about call charges")))))}const x=require("uuid"),D=e=>{const t=async()=>e.authorize();return{connect:t,fetchCustomerId:async()=>{const e=await t();return e?.consumerIdentity.idOnExternalPlatform},fetchThread:async a=>(await t(),e.getThread(a)),fetchMessages:async(e,a)=>{await t();const n=await e.recover(a),o=[];let l=n.messages;for(;l.length;){l.map((e=>o.push(e)));try{l=(await e.loadMoreMessages()).data.messages}catch(e){l=[]}}return o}}},G=({errors:e})=>{const a=Object.keys(e),n=e=>{e.preventDefault();const t=e.target.getAttribute("data-key");document.querySelector(`#wc-${t}`).focus()};return 0===a.length?null:t().createElement("div",{className:"govuk-error-summary govuk-!-static-margin-bottom-7","data-module":"govuk-error-summary",tabIndex:"-1"},t().createElement("div",{role:"alert"},t().createElement("h2",{id:"wc-error",className:"wc-error-summary__title govuk-error-summary__title"},"There is a problem"),t().createElement("div",{className:"govuk-error-summary__body"},t().createElement("ul",{className:"govuk-list govuk-error-summary__list wc-error-summary__list"},a.map((a=>t().createElement("li",{key:a},t().createElement("a",{href:"#","data-key":a,onClick:n},e[a]))))))))},q=500;function O({onPreChatScreen:a}){const{sdk:n,setCustomerId:o,setThreadId:l,setThread:s,setLiveRegionText:c}=N(),{fetchCustomerId:i,fetchThread:u}=D(n),[d,m]=(0,e.useState)({}),[g,h]=(0,e.useState)(0),[E,w]=(0,e.useState)(!1),v=(0,e.useRef)(),b=(0,e.useRef)(),y=q>=g;let f=`You have ${q-g} characters remaining`;y||(f=`You have ${g-q} characters too many`),(0,e.useEffect)((()=>{Object.keys(d).length&&document.querySelector(".govuk-error-summary")?.focus()}),[d]);const p=E?"Requesting...":"Request chat";return(0,e.useEffect)((()=>{E&&c(p)}),[E]),t().createElement(t().Fragment,null,t().createElement(L,null),t().createElement("div",{className:"wc-body"},t().createElement("div",{className:"wc-content"},t().createElement("a",{href:"#",className:"wc-back-link govuk-back-link",onClick:a},"What you can use webchat for"),t().createElement(G,{errors:d}),t().createElement("h3",{id:"wc-subtitle",className:"wc-heading","aria-live":"polite"},"Your name and question"),t().createElement("form",null,t().createElement("div",{className:r("wc-form-group","govuk-form-group",d.name&&"govuk-form-group--error")},t().createElement("label",{className:"wc-label govuk-label",htmlFor:"wc-name"},"Your name"),d.name&&t().createElement("p",{className:"govuk-error-message"},t().createElement("span",{className:"govuk-visually-hidden"},"Error:")," ",d.name),t().createElement("input",{ref:v,className:r("wc-input","govuk-input",d.name&&"govuk-input--error"),id:"wc-name",name:"name",type:"text","data-testid":"request-chat-user-name"})),t().createElement("div",{className:"wc-form-group govuk-character-count","data-module":"govuk-character-count","data-maxlength":"500"},t().createElement("div",{className:r("govuk-form-group",d.question&&"govuk-form-group--error")},t().createElement("label",{className:"wc-label govuk-label",htmlFor:"wc-question"},"Your question"),d.question&&t().createElement("p",{className:"govuk-error-message"},t().createElement("span",{className:"govuk-visually-hidden"},"Error:"),d.question),t().createElement("textarea",{ref:b,id:"wc-question",name:"question",rows:"5","aria-describedby":"wc-question-info",onChange:e=>{h(e.target.value.length)},className:r("wc-textarea","govuk-textarea","govuk-js-character-count",!y||d.question?"govuk-textarea--error":""),"data-testid":"request-chat-user-question"}),t().createElement("div",{id:"wc-question-info",className:"wc-hint govuk-hint govuk-char-count__msg",style:{color:y?"":"#d4351c"},"aria-hidden":"true"},f),t().createElement("div",{className:"govuk-character-count__sr-status govuk-visually-hidden","aria-live":"polite"},f))),t().createElement("div",{className:"wc-inset-text govuk-inset-text"},"By selecting 'Request chat' you agree to the terms of our ",t().createElement("a",{href:"https://check-for-flooding.service.gov.uk/privacy-notice",target:"_blank",rel:"noreferrer",className:"govuk-link"},"privacy notice"),"."),t().createElement("button",{className:"wc-button govuk-button govuk-!-margin-top-1","data-module":"govuk-button",onClick:async e=>{if(e.preventDefault(),E)return;const t={};if(0===v.current.value.length&&(t.name="Enter your name"),0===b.current.value.length&&(t.question="Enter your question"),b.current.value.length>q&&(t.question="Your question must be 500 characters or less"),0===Object.keys(t).length)try{w(!0);const e=x.v4(),t=await i(),a=await u(e);n.getCustomer().setName(v.current.value),await a.startChat(b.current.value||"Begin conversation"),o(t),l(e),s(a),a.setCustomField("threadid",e)}catch(e){console.log("[Request chat Error]",e)}m(t)},"aria-disabled":E},p)))))}const M=require("lodash.debounce");var R=a.n(M);function F({children:e}){return t().createElement("div",{className:"wc-footer"},e)}function B({message:e,previousMessage:a}){const n="outbound"===e.direction,o=e?.direction===a?.direction;return t().createElement("li",{className:r("wc-chat__message",n?"outbound":"inbound")},t().createElement("div",{className:"wc-chat__from"},o?null:t().createElement("span",{className:r(n?"outbound":"inbound")},n?e.assignee:"You"),t().createElement("span",{className:"govuk-visually-hidden"},":")),t().createElement("div",{className:r("wc-chat__text",n?"outbound":"inbound")},m(e.text)))}const U=(t,a)=>{(0,e.useEffect)((()=>{if(t){t.style.height="0px";const e=t.scrollHeight;t.style.height=`${e}px`}}),[t,a])},$=(e,t,a)=>{if("UNAVAILABLE"===e)return"Webchat is not currently available";if(!t)return"Connecting to Floodline";switch(t){case"closed":case"resolved":return a?`${a} ended the session`:"Session ended by advisor";default:return a?`You are speaking with ${a}`:"Waiting for an adviser"}};function Y({onEndChatScreen:a,onSettingsScreen:n}){const{availability:o,thread:l,messages:r,agent:s,agentStatus:c,isAgentTyping:i,isChatOpen:u,settings:d,isKeyboard:m,setLiveRegionText:g}=N(),[E,w]=(0,e.useState)(""),[v,y]=(0,e.useState)(!1),f=(0,e.useRef)();U(f.current,E),(0,e.useEffect)((()=>{if(d.scroll&&0!==r.length){const e=document.querySelector(".wc-body");e.scrollTop=e.scrollHeight}}),[r,i]),(0,e.useEffect)((()=>{const e=document.querySelector(".wc-form__label");0===E.length?e.classList.remove("govuk-visually-hidden"):e.classList.add("govuk-visually-hidden")}),[E]);const p=s?.nickname||s?.firstName,k=$(o,c,p);(0,e.useEffect)((()=>(k&&g(`Floodline webchat - ${k}`),()=>{g()})),[k]),(0,e.useEffect)((()=>(i&&u&&g(`${p} is typing...`),()=>{g()})),[i,u]),(0,e.useEffect)((()=>{const e=r[r.length-1];return"closed"!==c&&"outbound"===e?.direction&&g(`${p} said: ${e.text}`),()=>{g()}}),[r]);const S=()=>{if(0!==f.current.value.length&&"closed"!==c){try{const e=f.current.value.trim();l.sendTextMessage(e),g(`You said: ${e}`)}catch(e){console.log("[Chat Error] sendMessage",e)}w("")}},_=()=>{const e=h(r);document.querySelector("#transcript-download").setAttribute("href",`data:text/plain;charset=utf-8,${e}`)},T=(0,e.useCallback)(R()((()=>{l.keystroke(),setTimeout((()=>{l.stopTyping()}),b)}),100),[l]),C=e=>{if("Enter"!==e.key||e.shiftKey)" "===e.key?("end-chat"===e.target.id&&a(e),"wc-settings"===e.target.id&&n(e)):T();else switch(e.target.id){case"text-area":e.preventDefault(),S();break;case"end-chat":a(e);break;case"wc-settings":n(e);break;case"transcript-download":_()}};return t().createElement(t().Fragment,null,t().createElement(L,null),t().createElement("div",{className:"wc-status"},t().createElement("p",{className:"wc-status__availability"},k),t().createElement("a",{id:"end-chat",className:"wc-status__link",href:"#","data-module":"govuk-button",role:"button",onClick:a,onKeyDown:C},"End chat")),t().createElement("div",{className:"wc-body",tabIndex:"0"},t().createElement("ul",{className:"wc-chat"},r.length?r.map(((e,a)=>t().createElement(B,{key:e.id,message:e,previousMessage:r[a-1]}))):null,i?t().createElement("li",{className:"wc-chat__message outbound"},t().createElement("div",{className:"wc-chat__from"},p," is typing"),t().createElement("div",{className:"wc-chat__text outbound"},t().createElement("svg",{width:"28",height:"16",x:"0px",y:"0px",viewBox:"0 0 28 16"},t().createElement("circle",{stroke:"none",cx:"3",cy:"8",r:"3",fill:"currentColor"}),t().createElement("circle",{stroke:"none",cx:"14",cy:"8",r:"3",fill:"currentColor"}),t().createElement("circle",{stroke:"none",cx:"25",cy:"8",r:"3",fill:"currentColor"})))):null)),t().createElement(F,null,t().createElement("form",{className:"wc-form"+(v?" wc-focus-within":""),noValidate:!0,onSubmit:e=>{e.preventDefault(),S()}},t().createElement("label",{className:"govuk-label wc-form__label",htmlFor:"wc-form-textarea"},"Your message",t().createElement("span",{className:"govuk-visually-hidden"}," (enter key submits)")),t().createElement("textarea",{ref:f,rows:"1","aria-required":"true",className:"wc-form__textarea",id:"text-area",name:"message",onChange:e=>{w(e.target?.value)},onKeyDown:C,onFocus:()=>{y(m)},onBlur:()=>{y(!1)},value:E}),t().createElement("input",{type:"submit",className:"wc-form__button govuk-button",value:"Send","data-prevent-double-click":"true"})),t().createElement("div",{className:"wc-footer__settings"},t().createElement("a",{href:"#",id:"wc-settings",className:"wc-footer__settings-link","data-module":"govuk-button",onKeyDown:C,onClick:n},"Settings"),t().createElement("a",{href:"#",id:"transcript-download",className:"wc-footer__settings-link","data-module":"govuk-button",download:"floodline-webchat-transcript.txt",onKeyDown:C,onClick:_},"Save chat"))))}function K(){return t().createElement(t().Fragment,null,t().createElement(L,null),t().createElement("div",{className:"wc-body"},t().createElement("h3",{id:"wc-subtitle",className:"govuk-heading-m"},"Webchat is currently not available"),t().createElement("p",{className:"govuk-body-s"},"Try again later, or call Floodline:"),t().createElement("p",{className:"govuk-body-s"},t().createElement("strong",null,"Floodline helpline"),t().createElement("br",null),"Telephone: 0345 988 1188",t().createElement("br",null),"Textphone: 0345 602 6340",t().createElement("br",null),"Open 24 hours a day, 7 days a week",t().createElement("br",null),t().createElement("a",{className:"govuk-link",href:"https://gov.uk/call-charges"},"Find out more about call charges")),t().createElement("p",{className:"govuk-body-s"},"We're running webchat as a trial, it will not always be available.")))}function V({onChatScreen:a,onEndChatConfirm:n}){const{setCustomerId:o,setThreadId:l,setMessages:r,agentStatus:s,thread:c,threadId:i,setUnseenCount:u,isKeyboard:d}=N(),m=async e=>{e.preventDefault(),window.localStorage.setItem("tmpThreadId",i),l(),r([]),o(),c.lastMessageSeen(),u(0),"closed"!==s&&c.endChat(),n(e)};(0,e.useEffect)((()=>{d&&setTimeout((()=>{document.querySelector("#confirm-endchat").focus()}),10)}),[]);const g=e=>{"Enter"!==e.key&&" "!==e.key||"confirm-endchat"!==e.target.id||m(e),"Enter"!==e.key&&" "!==e.key||"resume-chat"!==e.target.id||a(e)};return t().createElement(t().Fragment,null,t().createElement(L,null),t().createElement("div",{className:"wc-body"},t().createElement("div",{className:"wc-content"},t().createElement("h3",{id:"wc-subtitle",className:"wc-heading","aria-live":"polite"},"Are you sure you want to end the chat?"),t().createElement("div",{className:"govuk-button-group"},t().createElement("a",{id:"confirm-endchat",href:"#endChat",role:"button",className:"wc-button govuk-button","data-module":"govuk-button",onClick:m,onKeyDown:g},"Yes, end chat"),t().createElement("a",{id:"resume-chat",href:"#resumeChat",role:"button",className:"wc-link govuk-link","data-module":"govuk-button",onClick:a,onKeyDown:g},"No, resume chat")))))}function P({onCancel:a}){const{settings:n,setSettings:o}=N(),[l,r]=(0,e.useState)(n.audio),[s,c]=(0,e.useState)(n.scroll),i=e=>{e.preventDefault(),o({audio:l,scroll:s}),a(e)},u=e=>{"Enter"!==e.key&&" "!==e.key||"settings-save"!==e.target.id?"Enter"!==e.key&&" "!==e.key||"settings-cancel"!==e.target.id||a(e):i(e)};return t().createElement(t().Fragment,null,t().createElement(L,null),t().createElement("div",{className:"wc-body"},t().createElement("div",{className:"wc-content"},t().createElement("fieldset",{className:"govuk-fieldset govuk-!-margin-bottom-4"},t().createElement("legend",{className:"govuk-fieldset__legend govuk-fieldset__legend"},t().createElement("h3",{id:"wc-subtitle",className:"wc-heading"},"Change settings")),t().createElement("div",{className:"govuk-checkboxes govuk-checkboxes--small","data-module":"govuk-checkboxes"},t().createElement("div",{className:"govuk-checkboxes__item"},t().createElement("input",{id:"audio",name:"audio",type:"checkbox",value:"audio",className:"govuk-checkboxes__input",defaultChecked:l,onChange:()=>r(!l)}),t().createElement("label",{className:"wc-label govuk-label govuk-checkboxes__label",htmlFor:"audio"},"Play a sound when receiving a new message")),t().createElement("div",{className:"govuk-checkboxes__item"},t().createElement("input",{id:"scroll",name:"scroll",type:"checkbox",value:"scroll",className:"govuk-checkboxes__input",defaultChecked:s,onChange:()=>c(!s)}),t().createElement("label",{className:"wc-label govuk-label govuk-checkboxes__label",htmlFor:"scroll"},"Scroll automatically to a new message")))),t().createElement("div",{className:"govuk-button-group"},t().createElement("a",{id:"settings-save",href:"#",className:"wc-button govuk-button","data-module":"govuk-button",role:"button",onClick:i,onKeyDown:u},"Save"),t().createElement("a",{id:"settings-cancel",href:"#",className:"wc-link govuk-link","data-module":"govuk-button",role:"button",onClick:a,onKeyDown:u},"Cancel")))))}function H({onCancel:e}){const a=()=>{const e=window.localStorage.getItem("tmpThreadId");window.location.href=`https://defragroup.eu.qualtrics.com/jfe/form/SV_8dgFSJcxxIfqx5Y?Id=${e}&Source=${window.location.href}`,window.localStorage.removeItem("tmpThreadId")},n=async t=>{window.localStorage.removeItem("tmpThreadId"),e(t)},o=e=>{"Enter"!==e.key&&" "!==e.key||("feedback-close"===e.target.id&&n(e),"feedback-send"===e.target.id&&a())};return t().createElement(t().Fragment,null,t().createElement(L,null),t().createElement("div",{className:"wc-body"},t().createElement("div",{className:"wc-content"},t().createElement("h3",{id:"wc-subtitle",className:"wc-heading"},"Give feedback on Floodline webchat"),t().createElement("p",null,"We're running webchat as a trial. you can ",t().createElement("a",{id:"feedback-send",className:"govuk-link",href:"#",target:"_blank",rel:"noreferrer",onKeyDown:o,onClick:a},"give feedback")," to help us improve it."),t().createElement("p",null,t().createElement("a",{id:"feedback-close",className:"wc-link govuk-link",href:"#","data-module":"govuk-button",role:"button",onKeyDown:o,onClick:n},"Close")))))}const j=()=>{const{agentStatus:a,liveRegionText:n,setLiveRegionText:o}=N(),[l,r]=(0,e.useState)(),[s,c]=(0,e.useState)(),i="closed"===a||null===a,u=()=>{r(),c()},d=(0,e.useCallback)(R()((e=>{l?c(e):r(e)}),2e3),[l,s]);return(0,e.useEffect)((()=>(n&&(u(),d(n)),i&&(u(),o()),()=>{u(),o()})),[n]),t().createElement(t().Fragment,null,t().createElement("div",{className:"wc-live",role:"status","aria-atomic":"true"},l),t().createElement("div",{className:"wc-live",role:"status","aria-atomic":"true"},s))},W="aria-hidden",J="data-wc-inert",Z=e=>{for(const t of document.body.children)"wc-panel"!==t.id&&(e&&!t.getAttribute(W)?(t.setAttribute(W,"true"),t.setAttribute(J,"")):t.hasAttribute(J)&&(t.removeAttribute(W),t.removeAttribute(J)))},X=t=>{const[a,n]=(0,e.useState)([]),o=(0,e.useCallback)((e=>{const t=document.querySelector("#wc-panel");"Tab"===e.key&&(t&&!document.activeElement.closest("#wc-panel")&&t.focus(),e.shiftKey?(document.activeElement===a[0]||document.activeElement===document.querySelector("#wc-panel"))&&(a[a.length-1].focus(),e.preventDefault()):document.activeElement===a[a.length-1]&&(a[0].focus(),e.preventDefault()))}),[a]);(0,e.useEffect)((()=>{n((()=>{const e=document.body.querySelectorAll(["#wc-panel a:not([disabled])","#wc-panel button:not([disabled])","#wc-panel select:not([disabled])","#wc-panel input:not([disabled])","#wc-panel textarea:not([disabled])",'#wc-panel *[tabindex="0"]:not([disabled])'].join(","));return Array.from(e).filter((e=>!e.closest("[hidden]")&&!e.closest('[aria-hidden="true"]')))})())}),[t]),(0,e.useEffect)((()=>(Z(!0),document.querySelector("#wc-panel").focus(),document.addEventListener("keydown",o),()=>{Z(),document.removeEventListener("keydown",o)})),[a])};function z(){const{sdk:a,availability:n,instigatorId:o,thread:l,threadId:c,setThread:i,setThreadId:u,setChatVisibility:d,setMessages:m,setUnseenCount:g,isMobile:h,isKeyboard:E}=N(),{fetchThread:w,fetchMessages:v}=D(a),[b,y]=(0,e.useState)(c?2:0);X(b);const f=(0,e.useCallback)((e=>{"Escape"!==e.key&&"Esc"!==e.key||(c&&(l?.lastMessageSeen(),g(0)),d(!1),I())}),[l,c,g,d]);(0,e.useEffect)((()=>()=>{document.getElementById(o)?.focus()}),[]),(0,e.useEffect)((()=>(document.body.classList.remove("wc-u-hidden"),document.getElementsByTagName("html")[0].classList.add("wc-u-html"),document.body.classList.add("wc-u-body"),()=>{document.getElementsByTagName("html")[0].classList.remove("wc-u-html"),document.body.classList.remove("wc-u-body")})),[h]),(0,e.useEffect)((()=>(document.addEventListener("keydown",f),()=>{document.removeEventListener("keydown",f)})),[f,d]),(0,e.useEffect)((()=>{c&&(l?(l.lastMessageSeen(),g(0),y(2)):(async()=>{try{const e=await w(c);i(e);const t=await v(e,c);m(t)}catch(e){console.log("[Chat Error] fetchThread",e),u(),i(),y(0)}})())}),[l,c]);const p=e=>t=>{t.preventDefault(),y(e)},k=p(0),S=p(1),_=p(2),T=p(3),C=p(4),L=p(5);let x;switch(b){case 0:default:x=t().createElement(A,{onContinue:S});break;case 1:x=t().createElement(O,{onPreChatScreen:k});break;case 2:x=t().createElement(Y,{onSettingsScreen:L,onEndChatScreen:T});break;case 3:x=t().createElement(V,{onChatScreen:_,onEndChatConfirm:C});break;case 4:x=t().createElement(H,{onCancel:()=>{d(!1),I()}});break;case 5:x=t().createElement(P,{onCancel:_})}"UNAVAILABLE"===n&&(x=t().createElement(K,null));const G=t().createElement("div",{id:"wc-panel",role:"dialog",className:r("wc-panel",E&&"wc-focus-visible"),tabIndex:"-1","aria-modal":"true","aria-labelledby":"wc-header wc-subtitle"},t().createElement("div",{className:"wc-panel__inner"},x),t().createElement(j,null));return t().createElement(t().Fragment,null,(0,s.createPortal)(G,document.body))}const Q=()=>{const{threadId:e,setInstigatorId:a}=N();if(!e)return null;const n=document.getElementById("webchat-skip-link-container");return n?t().createElement(t().Fragment,null,(0,s.createPortal)(t().createElement("a",{id:"webchat-skip-link",href:"#webchat",className:"govuk-skip-link","data-module":"govuk-skip-link",onClick:e=>{e.preventDefault(),a(e.target.id),window.location.hash="#webchat"},"data-wc-skiplink":!0,"data-wc-open-btn":!0},"Skip to webchat"),n)):null},{stripPageTitle:ee}=a(792);function te(){const{availability:a,isChatOpen:n,setChatVisibility:o,unseenCount:l,threadId:s,setUnseenCount:c,setInstigatorId:i,setLiveRegionText:u}=N(),d=(0,e.useRef)(),m=l>1?"new messages":"new message",g=l>0&&!n,h=ee(document.title),E=e=>{e.preventDefault(),c(0),o(!n),i(e.target.id),n?I():C()},w=e=>{" "===e.key&&e.preventDefault()},v=e=>{" "===e.key&&(c(0),o(!n))};switch((0,e.useEffect)((()=>{g&&(document.title=`(${l} ${m}) - ${h}`)}),[l]),(0,e.useEffect)((()=>(g&&u(`Floodline webchat - ${l} ${m}`),()=>{u()})),[l,n]),(0,e.useEffect)((()=>{const e=()=>{if(!s)return;if("AVAILABLE"!==a)return;const e=d.current.parentElement.getBoundingClientRect().top+35>(window.innerHeight||document.documentElement.clientHeight),t=!n&&e;document.documentElement.classList.toggle("wc-u-scroll-padding",t),document.body.classList.toggle("wc-u-scroll-padding",t),d.current.classList.toggle("wc-availability--fixed",t)};return document.addEventListener("scroll",e),e(),()=>{document.removeEventListener("scroll",e)}}),[s,n,a]),a){case"AVAILABLE":return t().createElement(t().Fragment,null,t().createElement("div",{className:r("wc-availability",n&&"wc-open"),ref:d},t().createElement("div",{className:"wc-availability__inner"},t().createElement("a",{id:"webchat-start-chat-link",className:"wc-availability__link",href:"#webchat",draggable:"false",onClick:E,onKeyUp:v,onKeyDown:w,role:"button","data-module":"govuk-button"},s?t().createElement(t().Fragment,null,"Show chat"):t().createElement(t().Fragment,null,"Start chat"),g?t().createElement("span",{className:"wc-availability__unseen"},l,t().createElement("span",{className:"govuk-visually-hidden"}," ",m)):null))),n?t().createElement(z,null):t().createElement(j,null),t().createElement(Q,null));case"EXISTING":case"UNAVAILABLE":return t().createElement("p",{className:"govuk-body"},"When it is available, a 'start chat' link will appear.");default:return t().createElement("p",{className:"govuk-body"},"Checking availability")}}const ae=async e=>{const t=new(window.AudioContext||window.webkitAudioContext);if("suspended"===t.state){const e=["touchstart","touchend","mousedown","wheel","keydown","click"],a=n=>{e.forEach((e=>{document.body.removeEventListener(e,a)})),t.resume()};e.forEach((e=>{document.body.addEventListener(e,a,!1)}))}const a=await fetch(e),n=await a.arrayBuffer(),o=await t.decodeAudioData(n);return()=>{const e=t.createBufferSource();e.buffer=o,e.connect(t.destination),e.start()}};async function ne(e,a){const n=new l.ChatSdk({brandId:a.brandId,channelId:a.channelId,customerId:window.localStorage.getItem(w)||"",environment:a.environment}),r=(0,o.createRoot)(e);let s,c;try{const e=await async function(e){const t=await fetch(e);return{availability:(await t.json()).availability||"UNAVAILABLE"}}(a.availabilityEndpoint);c=await ae(a.audioUrl),s=e.availability}catch(e){s="UNAVAILABLE"}r.render(t().createElement(_,{sdk:n,availability:s,playSound:c},t().createElement(te,null)))}})(),module.exports=n})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defra/flood-webchat",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "",
5
5
  "main": "dist/server.js",
6
6
  "browser": "dist/client.js",
@@ -1,14 +1,17 @@
1
1
  import React, { useEffect, useRef } from 'react'
2
2
 
3
- import { useApp } from '../../store/app/useApp'
4
3
  import { classnames } from '../../lib/classnames'
4
+ import { Panel } from '../panel/panel.jsx'
5
+ import { SkipLink } from '../skip-link.jsx'
6
+
7
+ import { useApp } from '../../store/useApp'
5
8
  import { historyPushState, historyReplaceState } from '../../lib/history.js'
6
9
  import { LiveRegion } from '../live-region.jsx'
7
10
 
8
11
  const { stripPageTitle } = require('../../../server/lib/utils')
9
12
 
10
13
  export function Availability () {
11
- const { availability, thread, isChatOpen, setChatVisibility, unseenCount, threadId, setUnseenCount, setInstigatorId, setLiveRegionText } = useApp()
14
+ const { availability, isChatOpen, setChatVisibility, unseenCount, threadId, setUnseenCount, setInstigatorId, setLiveRegionText } = useApp()
12
15
 
13
16
  const buttonRef = useRef()
14
17
 
@@ -20,8 +23,6 @@ export function Availability () {
20
23
 
21
24
  const onClick = e => {
22
25
  e.preventDefault()
23
- thread?.lastMessageSeen()
24
-
25
26
  setUnseenCount(0)
26
27
  setChatVisibility(!isChatOpen)
27
28
  setInstigatorId(e.target.id)
@@ -41,8 +42,6 @@ export function Availability () {
41
42
 
42
43
  const onKeyUp = event => {
43
44
  if (event.key === ' ') {
44
- thread?.lastMessageSeen()
45
-
46
45
  setUnseenCount(0)
47
46
  setChatVisibility(!isChatOpen)
48
47
  }
@@ -93,11 +92,6 @@ export function Availability () {
93
92
  }, [threadId, isChatOpen, availability])
94
93
 
95
94
  switch (availability) {
96
- case 'EXISTING':
97
- case 'UNAVAILABLE':
98
- return (
99
- <p className='govuk-body'>When it is available, a 'start chat' link will appear.</p>
100
- )
101
95
  case 'AVAILABLE':
102
96
  return (
103
97
  <>
@@ -129,9 +123,15 @@ export function Availability () {
129
123
  </a>
130
124
  </div>
131
125
  </div>
132
- {!isChatOpen && <LiveRegion />}
126
+ {!isChatOpen ? <LiveRegion /> : <Panel />}
127
+ <SkipLink />
133
128
  </>
134
129
  )
130
+ case 'EXISTING':
131
+ case 'UNAVAILABLE':
132
+ return (
133
+ <p className='govuk-body'>When it is available, a 'start chat' link will appear.</p>
134
+ )
135
135
  default:
136
136
  return (
137
137
  <p className='govuk-body'>Checking availability</p>
@@ -6,19 +6,15 @@ import { PanelHeader } from '../panel/panel-header.jsx'
6
6
  import { PanelFooter } from '../panel/panel-footer.jsx'
7
7
  import { Message } from '../message/message.jsx'
8
8
 
9
- import { useApp } from '../../store/app/useApp.js'
10
- import { useSdk } from '../../store/sdk/useSdk.js'
9
+ import { useApp } from '../../store/useApp.js'
11
10
  import { useTextareaAutosize } from '../../hooks/useTextareaAutosize.js'
12
11
  import { formatTranscript } from '../../lib/transform-messages.js'
13
12
  import { agentStatusHeadline } from '../../lib/agent-status-headline.js'
14
13
 
15
14
  export function Chat ({ onEndChatScreen, onSettingsScreen }) {
16
- const { availability, thread, isChatOpen, settings, isKeyboard, setLiveRegionText } = useApp()
17
- const { messages, agent, agentStatus, isAgentTyping } = useSdk()
15
+ const { availability, thread, messages, agent, agentStatus, isAgentTyping, isChatOpen, settings, isKeyboard, setLiveRegionText } = useApp()
18
16
 
19
17
  const [userMessage, setUserMessage] = useState('')
20
- const [agentName, setAgentName] = useState()
21
- const [connectionHeadlineText, setConnectionHeadlineText] = useState()
22
18
  const [focusVisibleWithin, setFocusVisibleWithin] = useState(false)
23
19
 
24
20
  const messageRef = useRef()
@@ -46,20 +42,19 @@ export function Chat ({ onEndChatScreen, onSettingsScreen }) {
46
42
  setUserMessage(e.target?.value)
47
43
  }
48
44
 
49
- useEffect(() => {
50
- setAgentName(agent?.nickname || agent?.firstName)
51
- setConnectionHeadlineText(agentStatusHeadline(availability, agentStatus, agentName))
52
- }, [agent, agentName, agentStatus])
45
+ const agentName = agent?.nickname || agent?.firstName
46
+
47
+ const connectionHeadlineText = agentStatusHeadline(availability, agentStatus, agentName)
53
48
 
54
49
  useEffect(() => {
55
- if (connectionHeadlineText && isChatOpen) {
50
+ if (connectionHeadlineText) {
56
51
  setLiveRegionText(`Floodline webchat - ${connectionHeadlineText}`)
57
52
  }
58
53
 
59
54
  return () => {
60
55
  setLiveRegionText()
61
56
  }
62
- }, [connectionHeadlineText, isChatOpen])
57
+ }, [connectionHeadlineText])
63
58
 
64
59
  useEffect(() => {
65
60
  if (isAgentTyping && isChatOpen) {
@@ -74,14 +69,14 @@ export function Chat ({ onEndChatScreen, onSettingsScreen }) {
74
69
  useEffect(() => {
75
70
  const lastAgentMessage = messages[messages.length - 1]
76
71
 
77
- if (agentStatus !== 'closed' && lastAgentMessage?.direction === 'outbound' && isChatOpen) {
72
+ if (agentStatus !== 'closed' && lastAgentMessage?.direction === 'outbound') {
78
73
  setLiveRegionText(`${agentName} said: ${lastAgentMessage.text}`)
79
74
  }
80
75
 
81
76
  return () => {
82
77
  setLiveRegionText()
83
78
  }
84
- }, [messages, isChatOpen])
79
+ }, [messages])
85
80
 
86
81
  const sendMessage = () => {
87
82
  if (messageRef.current.value.length === 0 || agentStatus === 'closed') {
@@ -156,18 +151,17 @@ export function Chat ({ onEndChatScreen, onSettingsScreen }) {
156
151
 
157
152
  <div className='wc-status'>
158
153
  <p className='wc-status__availability'>{connectionHeadlineText}</p>
159
- {thread &&
160
- <a
161
- id='end-chat'
162
- className='wc-status__link'
163
- href='#'
164
- data-module='govuk-button'
165
- role='button'
166
- onClick={onEndChatScreen}
167
- onKeyDown={handleKeyPress}
168
- >
169
- End chat
170
- </a>}
154
+ <a
155
+ id='end-chat'
156
+ className='wc-status__link'
157
+ href='#'
158
+ data-module='govuk-button'
159
+ role='button'
160
+ onClick={onEndChatScreen}
161
+ onKeyDown={handleKeyPress}
162
+ >
163
+ End chat
164
+ </a>
171
165
  </div>
172
166
 
173
167
  <div className='wc-body' tabIndex='0'>
@@ -1,13 +1,11 @@
1
1
  import React, { useEffect, useState, useCallback } from 'react'
2
2
  import debounce from 'lodash.debounce'
3
- import { useApp } from '../store/app/useApp'
4
- import { useSdk } from '../store/sdk/useSdk'
3
+ import { useApp } from '../store/useApp'
5
4
 
6
5
  const DEBOUNCE_MILLISECONDS = 2000
7
6
 
8
7
  export const LiveRegion = () => {
9
- const { liveRegionText, setLiveRegionText } = useApp()
10
- const { agentStatus } = useSdk()
8
+ const { agentStatus, liveRegionText, setLiveRegionText } = useApp()
11
9
 
12
10
  const [textA, setTextA] = useState()
13
11
  const [textB, setTextB] = useState()
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { useApp } from '../../store/app/useApp.js'
2
+ import { useApp } from '../../store/useApp.js'
3
3
  import { historyReplaceState } from '../../lib/history.js'
4
4
 
5
5
  export function PanelHeader () {
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect, useState, useCallback } from 'react'
2
2
  import { createPortal } from 'react-dom'
3
-
4
3
  import { classnames } from '../../lib/classnames.js'
4
+
5
5
  import { PreChat } from '../screens/pre-chat.jsx'
6
6
  import { RequestChat } from '../screens/request-chat.jsx'
7
7
  import { Chat } from '../chat/chat.jsx'
@@ -11,17 +11,18 @@ import { Settings } from '../screens/settings.jsx'
11
11
  import { Feedback } from '../screens/feedback.jsx'
12
12
  import { LiveRegion } from '../live-region.jsx'
13
13
 
14
- import { useApp } from '../../store/app/useApp.js'
14
+ import { useApp } from '../../store/useApp.js'
15
+ import { useChatSdk } from '../../store/useChatSdk.js'
15
16
  import { useFocusedElements } from '../../hooks/useFocusedElements.js'
16
17
  import { historyReplaceState } from '../../lib/history.js'
17
- import { SdkProvider } from '../../store/sdk/SdkProvider.jsx'
18
18
 
19
- export function Panel ({ initSdk, playSound }) {
20
- const { sdk, thread, availability, instigatorId, threadId, setSdk, setChatVisibility, setUnseenCount, isMobile, isKeyboard, isChatOpen } = useApp()
19
+ export function Panel () {
20
+ const { sdk, availability, instigatorId, thread, threadId, setThread, setThreadId, setChatVisibility, setMessages, setUnseenCount, isMobile, isKeyboard } = useApp()
21
+ const { fetchThread, fetchMessages } = useChatSdk(sdk)
21
22
 
22
23
  const [screen, setScreen] = useState(threadId ? 2 : 0)
23
24
 
24
- useFocusedElements(screen, isChatOpen)
25
+ useFocusedElements(screen)
25
26
 
26
27
  const onEscapeKey = useCallback(e => {
27
28
  if (e.key === 'Escape' || e.key === 'Esc') {
@@ -38,19 +39,18 @@ export function Panel ({ initSdk, playSound }) {
38
39
  * Focus previously focused element when closing the webchat
39
40
  */
40
41
  useEffect(() => {
41
- if (!isChatOpen) {
42
+ return () => {
42
43
  document.getElementById(instigatorId)?.focus()
43
44
  }
44
- }, [isChatOpen])
45
+ }, [])
45
46
 
46
47
  /**
47
- * We need ammend classes on the body element to handle mobile behaviour
48
- */
48
+ * We need ammend classes on the body element to handle mobile behaviour
49
+ */
49
50
  useEffect(() => {
50
51
  document.body.classList.remove('wc-u-hidden')
51
52
  document.getElementsByTagName('html')[0].classList.add('wc-u-html')
52
53
  document.body.classList.add('wc-u-body')
53
-
54
54
  return () => {
55
55
  document.getElementsByTagName('html')[0].classList.remove('wc-u-html')
56
56
  document.body.classList.remove('wc-u-body')
@@ -69,15 +69,33 @@ export function Panel ({ initSdk, playSound }) {
69
69
  }, [onEscapeKey, setChatVisibility])
70
70
 
71
71
  /**
72
- * Initialize SDK if theres a thread ID
72
+ * Recovers the thread if there is a threadId but no thread loaded in to state
73
73
  */
74
74
  useEffect(() => {
75
- if (threadId) {
76
- if (!thread) {
77
- setSdk(initSdk())
75
+ const recover = async () => {
76
+ try {
77
+ const fetchedThread = await fetchThread(threadId)
78
+ setThread(fetchedThread)
79
+
80
+ const fetchedMessages = await fetchMessages(fetchedThread, threadId)
81
+ setMessages(fetchedMessages)
82
+ } catch (err) {
83
+ console.log('[Chat Error] fetchThread', err)
84
+
85
+ setThreadId()
86
+ setThread()
87
+ setScreen(0)
78
88
  }
89
+ }
79
90
 
80
- setScreen(2)
91
+ if (threadId) {
92
+ if (thread) {
93
+ thread.lastMessageSeen()
94
+ setUnseenCount(0)
95
+ setScreen(2)
96
+ } else {
97
+ recover()
98
+ }
81
99
  }
82
100
  }, [thread, threadId])
83
101
 
@@ -100,38 +118,25 @@ export function Panel ({ initSdk, playSound }) {
100
118
  ScreenComponent = <PreChat onContinue={goToRequestChatScreen} />
101
119
  break
102
120
  case 1:
103
- ScreenComponent = <RequestChat initSdk={initSdk} onPreChatScreen={goToPreChatScreen} />
121
+ ScreenComponent = <RequestChat onPreChatScreen={goToPreChatScreen} />
104
122
  break
105
123
  case 2:
106
- ScreenComponent = (
107
- <SdkProvider sdk={sdk} playSound={playSound} onRecoverError={() => setScreen(0)}>
108
- <Chat onSettingsScreen={goToSettingsScreen} onEndChatScreen={goToEndChatScreen} />
109
- </SdkProvider>
110
- )
124
+ ScreenComponent = <Chat onSettingsScreen={goToSettingsScreen} onEndChatScreen={goToEndChatScreen} />
111
125
  break
112
126
  case 3:
113
- ScreenComponent = (
114
- <SdkProvider sdk={sdk} playSound={playSound}>
115
- <EndChat onChatScreen={goToChatScreen} onEndChatConfirm={goToFeedbackScreen} />
116
- </SdkProvider>
117
- )
127
+ ScreenComponent = <EndChat onChatScreen={goToChatScreen} onEndChatConfirm={goToFeedbackScreen} />
118
128
  break
119
129
  case 4:
120
130
  ScreenComponent = (
121
131
  <Feedback onCancel={() => {
122
132
  setChatVisibility(false)
123
133
  historyReplaceState()
124
- setScreen(0)
125
134
  }}
126
135
  />
127
136
  )
128
137
  break
129
138
  case 5:
130
- ScreenComponent = (
131
- <SdkProvider sdk={sdk} playSound={playSound}>
132
- <Settings onCancel={goToChatScreen} />
133
- </SdkProvider>
134
- )
139
+ ScreenComponent = <Settings onCancel={goToChatScreen} />
135
140
  break
136
141
  default:
137
142
  ScreenComponent = <PreChat onContinue={goToRequestChatScreen} />
@@ -142,7 +147,7 @@ export function Panel ({ initSdk, playSound }) {
142
147
  }
143
148
 
144
149
  const Component = (
145
- <div id='wc-panel' role='dialog' style={{ display: isChatOpen ? 'flex' : 'none' }} className={classnames('wc-panel', isKeyboard && 'wc-focus-visible')} tabIndex='-1' aria-modal='true' aria-labelledby='wc-header wc-subtitle' open={isChatOpen}>
150
+ <div id='wc-panel' role='dialog' className={classnames('wc-panel', isKeyboard && 'wc-focus-visible')} tabIndex='-1' aria-modal='true' aria-labelledby='wc-header wc-subtitle'>
146
151
  <div className='wc-panel__inner'>
147
152
  {ScreenComponent}
148
153
  </div>
@@ -1,21 +1,18 @@
1
1
  import React, { useEffect } from 'react'
2
2
  import { PanelHeader } from '../panel/panel-header.jsx'
3
- import { useApp } from '../../store/app/useApp.js'
4
- import { useSdk } from '../../store/sdk/useSdk.js'
3
+ import { useApp } from '../../store/useApp.js'
5
4
 
6
5
  export function EndChat ({ onChatScreen, onEndChatConfirm }) {
7
- const { thread, setSdk, setCustomerId, setThreadId, threadId, setUnseenCount, isKeyboard } = useApp()
8
- const { agentStatus, setMessages } = useSdk()
6
+ const { setCustomerId, setThreadId, setMessages, agentStatus, thread, threadId, setUnseenCount, isKeyboard } = useApp()
9
7
 
10
8
  const confirmEndChat = async e => {
11
9
  e.preventDefault()
12
10
 
13
11
  window.localStorage.setItem('tmpThreadId', threadId)
14
- thread?.lastMessageSeen()
15
- setSdk()
16
12
  setThreadId()
17
13
  setMessages([])
18
14
  setCustomerId()
15
+ thread.lastMessageSeen()
19
16
  setUnseenCount(0)
20
17
 
21
18
  // End chat if still open
@@ -3,14 +3,15 @@ import * as uuid from 'uuid'
3
3
 
4
4
  import { classnames } from '../../lib/classnames.js'
5
5
  import { PanelHeader } from '../panel/panel-header.jsx'
6
- import { useApp } from '../../store/app/useApp.js'
6
+ import { useApp } from '../../store/useApp.js'
7
+ import { useChatSdk } from '../../store/useChatSdk.js'
7
8
  import { ErrorSummary } from '../errorSummary/error-summary.jsx'
8
9
 
9
10
  const QUESTION_MAX_LENGTH = 500
10
11
 
11
- export function RequestChat ({ initSdk, onPreChatScreen }) {
12
- const { setSdk, setCustomerId, setThreadId, setThread, setLiveRegionText } = useApp()
13
-
12
+ export function RequestChat ({ onPreChatScreen }) {
13
+ const { sdk, setCustomerId, setThreadId, setThread, setLiveRegionText } = useApp()
14
+ const { fetchCustomerId, fetchThread } = useChatSdk(sdk)
14
15
  const [errors, setErrors] = useState({})
15
16
  const [questionLength, setQuestionLength] = useState(0)
16
17
  const [isButtonDisabled, setButtonDisabled] = useState(false)
@@ -71,22 +72,17 @@ export function RequestChat ({ initSdk, onPreChatScreen }) {
71
72
  try {
72
73
  setButtonDisabled(true)
73
74
  const threadId = uuid.v4()
75
+ const customerId = await fetchCustomerId()
76
+ const thread = await fetchThread(threadId)
74
77
 
75
- const sdk = initSdk()
76
- const conn = await sdk.authorize()
77
- const customerId = conn?.consumerIdentity.idOnExternalPlatform
78
-
79
- const thread = await sdk.getThread(threadId)
80
- thread.setCustomField('threadid', threadId)
81
-
82
- await sdk.getCustomer().setName(nameRef.current.value)
78
+ sdk.getCustomer().setName(nameRef.current.value)
83
79
 
84
80
  await thread.startChat(questionRef.current.value || 'Begin conversation')
85
81
 
86
- setSdk(sdk)
87
82
  setCustomerId(customerId)
88
83
  setThreadId(threadId)
89
84
  setThread(thread)
85
+ thread.setCustomField('threadid', threadId)
90
86
  } catch (err) {
91
87
  console.log('[Request chat Error]', err)
92
88
  }
@@ -1,7 +1,7 @@
1
1
  import React, { useState } from 'react'
2
2
  import { PanelHeader } from '../panel/panel-header.jsx'
3
3
 
4
- import { useApp } from '../../store/app/useApp.js'
4
+ import { useApp } from '../../store/useApp.js'
5
5
 
6
6
  export function Settings ({ onCancel }) {
7
7
  const { settings, setSettings } = useApp()
@@ -7,18 +7,16 @@ export function Unavailable () {
7
7
  <PanelHeader />
8
8
 
9
9
  <div className='wc-body'>
10
- <div className='wc-content'>
11
- <h3 id='wc-subtitle' className='govuk-heading-m'>Webchat is currently not available</h3>
12
- <p className='govuk-body-s'>Try again later, or call Floodline:</p>
13
- <p className='govuk-body-s'>
14
- <strong>Floodline helpline</strong>
15
- <br />Telephone: 0345 988 1188
16
- <br />Textphone: 0345 602 6340
17
- <br />Open 24 hours a day, 7 days a week
18
- <br /><a className='govuk-link' href='https://gov.uk/call-charges'>Find out more about call charges</a>
19
- </p>
20
- <p className='govuk-body-s'>We're running webchat as a trial, it will not always be available.</p>
21
- </div>
10
+ <h3 id='wc-subtitle' className='govuk-heading-m'>Webchat is currently not available</h3>
11
+ <p className='govuk-body-s'>Try again later, or call Floodline:</p>
12
+ <p className='govuk-body-s'>
13
+ <strong>Floodline helpline</strong>
14
+ <br />Telephone: 0345 988 1188
15
+ <br />Textphone: 0345 602 6340
16
+ <br />Open 24 hours a day, 7 days a week
17
+ <br /><a className='govuk-link' href='https://gov.uk/call-charges'>Find out more about call charges</a>
18
+ </p>
19
+ <p className='govuk-body-s'>We're running webchat as a trial, it will not always be available.</p>
22
20
  </div>
23
21
  </>
24
22
  )
@@ -1,6 +1,6 @@
1
1
  import React from 'react'
2
2
  import { createPortal } from 'react-dom'
3
- import { useApp } from '../store/app/useApp'
3
+ import { useApp } from '../store/useApp'
4
4
 
5
5
  export const SkipLink = () => {
6
6
  const { threadId, setInstigatorId } = useApp()
@@ -32,7 +32,7 @@ export const getFocusableElements = () => {
32
32
  return Array.from(elements).filter(e => !e.closest('[hidden]') && !e.closest('[aria-hidden="true"]'))
33
33
  }
34
34
 
35
- const useFocusedElements = (screen, isChatOpen) => {
35
+ const useFocusedElements = screen => {
36
36
  const [panelElements, setPanelElements] = useState([])
37
37
 
38
38
  const onKeyDown = useCallback(e => {
@@ -63,20 +63,18 @@ const useFocusedElements = (screen, isChatOpen) => {
63
63
  }, [screen])
64
64
 
65
65
  useEffect(() => {
66
- if (isChatOpen) {
67
- setAriaHidden(true)
66
+ setAriaHidden(true)
68
67
 
69
- const panelElement = document.querySelector('#wc-panel')
70
- panelElement.focus()
68
+ const panelElement = document.querySelector('#wc-panel')
69
+ panelElement.focus()
71
70
 
72
- document.addEventListener('keydown', onKeyDown)
73
- }
71
+ document.addEventListener('keydown', onKeyDown)
74
72
 
75
73
  return () => {
76
74
  setAriaHidden()
77
75
  document.removeEventListener('keydown', onKeyDown)
78
76
  }
79
- }, [panelElements, isChatOpen])
77
+ }, [panelElements])
80
78
  }
81
79
 
82
80
  export { useFocusedElements }
@@ -3,44 +3,31 @@ import { createRoot } from 'react-dom/client'
3
3
  import { ChatSdk } from '@nice-devone/nice-cxone-chat-web-sdk'
4
4
  import { Availability } from './components/availability/availability.jsx'
5
5
  import { checkAvailability } from './lib/check-availability'
6
- import { AppProvider } from './store/app/AppProvider.jsx'
6
+ import { AppProvider } from './store/AppProvider.jsx'
7
7
  import { CUSTOMER_ID_STORAGE_KEY } from './store/constants.js'
8
8
  import { messageNotification } from './lib/message-notification.js'
9
- import { SkipLink } from './components/skip-link.jsx'
10
- import { Panel } from './components/panel/panel.jsx'
11
9
 
12
10
  export async function init (container, options) {
13
- const root = createRoot(container)
14
-
15
- const initSdk = () => {
16
- return new ChatSdk({
17
- brandId: options.brandId,
18
- channelId: options.channelId,
19
- customerId: window.localStorage.getItem(CUSTOMER_ID_STORAGE_KEY) || '',
20
- environment: options.environment,
21
- onError: error => {
22
- console.log('ChatSdk onError', error)
23
- }
24
- })
25
- }
11
+ const sdk = new ChatSdk({
12
+ brandId: options.brandId,
13
+ channelId: options.channelId,
14
+ customerId: window.localStorage.getItem(CUSTOMER_ID_STORAGE_KEY) || '',
15
+ environment: options.environment
16
+ })
26
17
 
18
+ const root = createRoot(container)
27
19
  let availability
28
20
  let playSound
29
-
30
21
  try {
31
22
  const result = await checkAvailability(options.availabilityEndpoint)
32
-
33
23
  playSound = await messageNotification(options.audioUrl)
34
24
  availability = result.availability
35
25
  } catch (e) {
36
26
  availability = 'UNAVAILABLE'
37
27
  }
38
-
39
28
  root.render(
40
- <AppProvider availability={availability}>
29
+ <AppProvider sdk={sdk} availability={availability} playSound={playSound}>
41
30
  <Availability />
42
- <SkipLink />
43
- <Panel initSdk={initSdk} playSound={playSound} />
44
31
  </AppProvider>
45
32
  )
46
33
  }
@@ -1,14 +1,84 @@
1
1
  import React, { createContext, useEffect, useReducer, useMemo } from 'react'
2
- // import { ChatEvent } from '@nice-devone/nice-cxone-chat-web-sdk'
2
+ import { ChatEvent } from '@nice-devone/nice-cxone-chat-web-sdk'
3
3
 
4
4
  import { initialState, reducer } from './reducer.js'
5
- import { CUSTOMER_ID_STORAGE_KEY, THREAD_ID_STORAGE_KEY, SETTINGS_STORAGE_KEY, MESSAGES_UNSEEN_COUNT } from '../constants.js'
5
+ import { CUSTOMER_ID_STORAGE_KEY, THREAD_ID_STORAGE_KEY, SETTINGS_STORAGE_KEY, MESSAGES_UNSEEN_COUNT } from './constants.js'
6
6
 
7
7
  export const AppContext = createContext(initialState)
8
8
 
9
- export const AppProvider = ({ availability, children }) => {
9
+ export const AppProvider = ({ sdk, availability, playSound, children }) => {
10
10
  const [state, dispatch] = useReducer(reducer, initialState)
11
11
 
12
+ /**
13
+ * SDK event handlers
14
+ */
15
+ const onLiveChatRecovered = e => {
16
+ dispatch({ type: 'SET_AGENT', payload: e.detail.data.inboxAssignee })
17
+ dispatch({ type: 'SET_AGENT_STATUS', payload: e.detail.data.contact.status })
18
+ dispatch({ type: 'SET_UNSEEN_COUNT', payload: e.detail.data.contact.customerStatistics.unseenMessagesCount })
19
+ }
20
+
21
+ const onAssignedAgentChanged = e => {
22
+ dispatch({ type: 'SET_AGENT', payload: e.detail.data.inboxAssignee })
23
+ dispatch({ type: 'SET_AGENT_STATUS', payload: e.detail.data.case.status })
24
+ }
25
+
26
+ const onAgentTypingStarted = () => {
27
+ dispatch({ type: 'SET_AGENT_TYPING', payload: true })
28
+ }
29
+
30
+ const onAgentTypingEnded = () => {
31
+ dispatch({ type: 'SET_AGENT_TYPING', payload: false })
32
+ dispatch({ type: 'SET_LIVE_REGION_TEXT' })
33
+ }
34
+
35
+ const onMessageCreated = e => {
36
+ dispatch({ type: 'SET_MESSAGE', payload: e.detail.data.message })
37
+ dispatch({ type: 'SET_AGENT_STATUS', payload: e.detail.data.case.status })
38
+ dispatch({ type: 'SET_UNSEEN_COUNT', payload: e.detail.data.case.customerStatistics.unseenMessagesCount })
39
+
40
+ const isAudioOn = JSON.parse(window.localStorage.getItem(SETTINGS_STORAGE_KEY)).audio
41
+
42
+ if (isAudioOn && e.detail.data.message.direction === 'outbound' && playSound) {
43
+ playSound()
44
+ }
45
+ }
46
+
47
+ const onContactStatusChanged = e => {
48
+ dispatch({ type: 'SET_AGENT_STATUS', payload: e.detail.data.case.status })
49
+ }
50
+
51
+ const onMatchMedia = e => {
52
+ dispatch({ type: 'TOGGLE_IS_MOBILE', payload: e.matches })
53
+ }
54
+
55
+ const onKeydown = () => {
56
+ dispatch({ type: 'TOGGLE_IS_KEYBOARD', payload: true })
57
+ }
58
+
59
+ const onPointerdown = () => {
60
+ dispatch({ type: 'TOGGLE_IS_KEYBOARD', payload: false })
61
+ }
62
+
63
+ useEffect(() => {
64
+ sdk.onChatEvent(ChatEvent.LIVECHAT_RECOVERED, onLiveChatRecovered)
65
+ sdk.onChatEvent(ChatEvent.MESSAGE_CREATED, onMessageCreated)
66
+ sdk.onChatEvent(ChatEvent.AGENT_TYPING_STARTED, onAgentTypingStarted)
67
+ sdk.onChatEvent(ChatEvent.AGENT_TYPING_ENDED, onAgentTypingEnded)
68
+ sdk.onChatEvent(ChatEvent.ASSIGNED_AGENT_CHANGED, onAssignedAgentChanged)
69
+ sdk.onChatEvent(ChatEvent.CONTACT_STATUS_CHANGED, onContactStatusChanged)
70
+ // We need to know if it is a mobile and if it is a keyboard interaction
71
+ window.matchMedia('(max-width: 640px)').addEventListener('change', onMatchMedia)
72
+ window.addEventListener('keydown', onKeydown)
73
+ window.addEventListener('pointerdown', onPointerdown)
74
+ // Tidying up
75
+ return () => {
76
+ window.removeEventListener('change', onMatchMedia)
77
+ window.removeEventListener('keydown', onKeydown)
78
+ window.removeEventListener('pointerdown', onPointerdown)
79
+ }
80
+ }, [sdk])
81
+
12
82
  /**
13
83
  * Initialize customerId, threadId and whether the webchat should be open
14
84
  */
@@ -44,38 +114,9 @@ export const AppProvider = ({ availability, children }) => {
44
114
  }
45
115
  }, [])
46
116
 
47
- const onMatchMedia = e => {
48
- dispatch({ type: 'TOGGLE_IS_MOBILE', payload: e.matches })
49
- }
50
-
51
- const onKeydown = () => {
52
- dispatch({ type: 'TOGGLE_IS_KEYBOARD', payload: true })
53
- }
54
-
55
- const onPointerdown = () => {
56
- dispatch({ type: 'TOGGLE_IS_KEYBOARD', payload: false })
57
- }
58
-
59
- useEffect(() => {
60
- // We need to know if it is a mobile and if it is a keyboard interaction
61
- window.matchMedia('(max-width: 640px)').addEventListener('change', onMatchMedia)
62
- window.addEventListener('keydown', onKeydown)
63
- window.addEventListener('pointerdown', onPointerdown)
64
-
65
- return () => {
66
- window.removeEventListener('change', onMatchMedia)
67
- window.removeEventListener('keydown', onKeydown)
68
- window.removeEventListener('pointerdown', onPointerdown)
69
- }
70
- }, [])
71
-
72
117
  /**
73
118
  * State update functions
74
119
  */
75
- const setSdk = payload => {
76
- dispatch({ type: 'SET_SDK', payload })
77
- }
78
-
79
120
  const setChatVisibility = payload => {
80
121
  dispatch({ type: 'SET_CHAT_VISIBILITY', payload })
81
122
  }
@@ -92,6 +133,10 @@ export const AppProvider = ({ availability, children }) => {
92
133
  dispatch({ type: 'SET_THREAD', payload: thread })
93
134
  }
94
135
 
136
+ const setMessages = messages => {
137
+ dispatch({ type: 'SET_MESSAGES', payload: messages })
138
+ }
139
+
95
140
  const setSettings = data => {
96
141
  dispatch({ type: 'SET_SETTINGS', payload: data })
97
142
  }
@@ -113,15 +158,22 @@ export const AppProvider = ({ availability, children }) => {
113
158
  */
114
159
  const store = useMemo(() => ({
115
160
  ...state,
116
- setSdk,
161
+ sdk,
117
162
  setSettings,
118
163
  setCustomerId,
119
164
  setThreadId,
120
165
  setThread,
166
+ setMessages,
121
167
  setUnseenCount,
122
168
  setChatVisibility,
123
169
  setInstigatorId,
124
- setLiveRegionText
170
+ setLiveRegionText,
171
+ onLiveChatRecovered,
172
+ onAssignedAgentChanged,
173
+ onAgentTypingStarted,
174
+ onAgentTypingEnded,
175
+ onMessageCreated,
176
+ onContactStatusChanged
125
177
  }))
126
178
 
127
179
  return (
@@ -1,11 +1,5 @@
1
- import { CUSTOMER_ID_STORAGE_KEY, THREAD_ID_STORAGE_KEY, SETTINGS_STORAGE_KEY, MESSAGES_UNSEEN_COUNT } from '../constants'
2
-
3
- const setSdk = (state, payload) => {
4
- return {
5
- ...state,
6
- sdk: payload
7
- }
8
- }
1
+ import { transformMessages, transformMessage } from '../lib/transform-messages'
2
+ import { CUSTOMER_ID_STORAGE_KEY, THREAD_ID_STORAGE_KEY, SETTINGS_STORAGE_KEY, MESSAGES_UNSEEN_COUNT } from './constants'
9
3
 
10
4
  const setSettings = (state, payload) => {
11
5
  if (payload) {
@@ -46,6 +40,20 @@ const setThreadId = (state, payload) => {
46
40
  }
47
41
  }
48
42
 
43
+ const setChatVisibility = (state, payload) => {
44
+ return {
45
+ ...state,
46
+ isChatOpen: payload
47
+ }
48
+ }
49
+
50
+ const setAvailability = (state, payload) => {
51
+ return {
52
+ ...state,
53
+ availability: payload
54
+ }
55
+ }
56
+
49
57
  const setThread = (state, payload) => {
50
58
  return {
51
59
  ...state,
@@ -53,17 +61,39 @@ const setThread = (state, payload) => {
53
61
  }
54
62
  }
55
63
 
56
- const setChatVisibility = (state, payload) => {
64
+ const setMessages = (state, payload) => {
57
65
  return {
58
66
  ...state,
59
- isChatOpen: payload
67
+ messages: transformMessages(payload).reverse()
60
68
  }
61
69
  }
62
70
 
63
- const setAvailability = (state, payload) => {
71
+ const setMessage = (state, payload) => {
64
72
  return {
65
73
  ...state,
66
- availability: payload
74
+ message: transformMessage(payload),
75
+ messages: [...state.messages, transformMessage(payload)]
76
+ }
77
+ }
78
+
79
+ const setAgent = (state, payload) => {
80
+ return {
81
+ ...state,
82
+ agent: payload
83
+ }
84
+ }
85
+
86
+ const setAgentIsTyping = (state, payload) => {
87
+ return {
88
+ ...state,
89
+ isAgentTyping: payload
90
+ }
91
+ }
92
+
93
+ const setAgentStatus = (state, payload) => {
94
+ return {
95
+ ...state,
96
+ agentStatus: payload
67
97
  }
68
98
  }
69
99
 
@@ -104,13 +134,17 @@ const toggleIsKeyboard = (state, payload) => {
104
134
  }
105
135
 
106
136
  export const actionsMap = {
107
- SET_SDK: setSdk,
108
- SET_THREAD: setThread,
109
137
  SET_CHAT_VISIBILITY: setChatVisibility,
110
138
  SET_AVAILABILITY: setAvailability,
111
139
  SET_SETTINGS: setSettings,
112
140
  SET_CUSTOMER_ID: setCustomerId,
113
141
  SET_THREAD_ID: setThreadId,
142
+ SET_THREAD: setThread,
143
+ SET_MESSAGE: setMessage,
144
+ SET_MESSAGES: setMessages,
145
+ SET_AGENT: setAgent,
146
+ SET_AGENT_TYPING: setAgentIsTyping,
147
+ SET_AGENT_STATUS: setAgentStatus,
114
148
  SET_UNSEEN_COUNT: setUnseenCount,
115
149
  SET_INSTIGATOR_ID: setInstigatorId,
116
150
  SET_LIVE_REGION_TEXT: setLiveRegionText,
@@ -1,13 +1,16 @@
1
1
  import { actionsMap } from './actions-map'
2
2
 
3
3
  export const initialState = {
4
- sdk: null,
5
4
  availability: null,
6
5
  customerId: null,
7
6
  threadId: null,
8
7
  thread: null,
8
+ messages: [],
9
9
  unseenCount: 0,
10
10
  instigatorId: null,
11
+ agent: null,
12
+ agentStatus: null,
13
+ isAgentTyping: false,
11
14
  isChatOpen: false,
12
15
  isMobile: window.matchMedia('(max-width: 640px)').matches,
13
16
  isKeyboard: false,
@@ -0,0 +1,37 @@
1
+ export const useChatSdk = sdk => {
2
+ const connect = async () => sdk.authorize()
3
+
4
+ const fetchCustomerId = async () => {
5
+ const response = await connect()
6
+ return response?.consumerIdentity.idOnExternalPlatform
7
+ }
8
+
9
+ const fetchThread = async threadId => {
10
+ await connect()
11
+ return sdk.getThread(threadId)
12
+ }
13
+
14
+ const fetchMessages = async (thread, threadId) => {
15
+ await connect()
16
+
17
+ const recovered = await thread.recover(threadId)
18
+
19
+ const allMessages = []
20
+ let fetchedMessages = recovered.messages
21
+
22
+ while (fetchedMessages.length) {
23
+ fetchedMessages.map(msg => allMessages.push(msg))
24
+
25
+ try {
26
+ const response = await thread.loadMoreMessages()
27
+ fetchedMessages = response.data.messages
28
+ } catch (err) {
29
+ fetchedMessages = []
30
+ }
31
+ }
32
+
33
+ return allMessages
34
+ }
35
+
36
+ return { connect, fetchCustomerId, fetchThread, fetchMessages }
37
+ }
@@ -1,141 +0,0 @@
1
- import React, { createContext, useEffect, useReducer, useMemo } from 'react'
2
- import { ChatEvent } from '@nice-devone/nice-cxone-chat-web-sdk'
3
-
4
- import { initialState, reducer } from './reducer.js'
5
- import { SETTINGS_STORAGE_KEY } from '../constants.js'
6
- import { useApp } from '../app/useApp.js'
7
-
8
- export const SdkContext = createContext(initialState)
9
-
10
- export const SdkProvider = ({ sdk, playSound, onRecoverError, children }) => {
11
- const [state, dispatch] = useReducer(reducer, initialState)
12
- const { thread, threadId, setThread, setThreadId, setUnseenCount } = useApp()
13
-
14
- /**
15
- * SDK event handlers
16
- */
17
- const onLiveChatRecovered = e => {
18
- dispatch({ type: 'SET_AGENT', payload: e.detail.data.inboxAssignee })
19
- dispatch({ type: 'SET_AGENT_STATUS', payload: e.detail.data.contact.status })
20
- setUnseenCount(e.detail.data.contact.customerStatistics.unseenMessagesCount)
21
- }
22
-
23
- const onAssignedAgentChanged = e => {
24
- dispatch({ type: 'SET_AGENT', payload: e.detail.data.inboxAssignee })
25
- dispatch({ type: 'SET_AGENT_STATUS', payload: e.detail.data.case.status })
26
- }
27
-
28
- const onAgentTypingStarted = () => {
29
- dispatch({ type: 'SET_AGENT_TYPING', payload: true })
30
- }
31
-
32
- const onAgentTypingEnded = () => {
33
- dispatch({ type: 'SET_AGENT_TYPING', payload: false })
34
- dispatch({ type: 'SET_LIVE_REGION_TEXT' })
35
- }
36
-
37
- const onMessageCreated = e => {
38
- dispatch({ type: 'SET_MESSAGE', payload: e.detail.data.message })
39
- dispatch({ type: 'SET_AGENT_STATUS', payload: e.detail.data.case.status })
40
-
41
- setUnseenCount(e.detail.data.case.customerStatistics.unseenMessagesCount)
42
-
43
- const isAudioOn = JSON.parse(window.localStorage.getItem(SETTINGS_STORAGE_KEY)).audio
44
-
45
- if (isAudioOn && e.detail.data.message.direction === 'outbound' && playSound) {
46
- playSound()
47
- }
48
- }
49
-
50
- const onContactStatusChanged = e => {
51
- dispatch({ type: 'SET_AGENT_STATUS', payload: e.detail.data.case.status })
52
- }
53
-
54
- useEffect(() => {
55
- if (sdk) {
56
- sdk.onChatEvent(ChatEvent.LIVECHAT_RECOVERED, onLiveChatRecovered)
57
- sdk.onChatEvent(ChatEvent.MESSAGE_CREATED, onMessageCreated)
58
- sdk.onChatEvent(ChatEvent.AGENT_TYPING_STARTED, onAgentTypingStarted)
59
- sdk.onChatEvent(ChatEvent.AGENT_TYPING_ENDED, onAgentTypingEnded)
60
- sdk.onChatEvent(ChatEvent.ASSIGNED_AGENT_CHANGED, onAssignedAgentChanged)
61
- sdk.onChatEvent(ChatEvent.CONTACT_STATUS_CHANGED, onContactStatusChanged)
62
- }
63
- }, [sdk])
64
-
65
- const fetchMessages = async threadItem => {
66
- const recovered = await threadItem.recover()
67
-
68
- const allMessages = []
69
-
70
- let fetchedMessages = recovered.messages
71
-
72
- while (fetchedMessages.length) {
73
- fetchedMessages.map(msg => allMessages.push(msg))
74
-
75
- try {
76
- const response = await threadItem.loadMoreMessages()
77
- fetchedMessages = response.data.messages
78
- } catch (err) {
79
- fetchedMessages = []
80
- }
81
- }
82
-
83
- return allMessages
84
- }
85
-
86
- /**
87
- * Recovers the thread if there is a threadId but no thread loaded in to state
88
- */
89
- useEffect(() => {
90
- const recover = async () => {
91
- try {
92
- await sdk.authorize()
93
-
94
- const fetchedThread = await sdk.getThread(threadId)
95
- const fetchedMessages = await fetchMessages(fetchedThread)
96
-
97
- setThread(fetchedThread)
98
- setMessages(fetchedMessages)
99
- } catch (err) {
100
- console.log('[Chat Error] fetchThread', err)
101
- setThreadId()
102
- setThread()
103
- onRecoverError()
104
- }
105
- }
106
-
107
- if (sdk && threadId && !thread) {
108
- console.log('recovering chat...')
109
- recover()
110
- }
111
- }, [sdk, thread, threadId])
112
-
113
- /**
114
- * State update functions
115
- */
116
- const setMessages = messages => {
117
- dispatch({ type: 'SET_MESSAGES', payload: messages })
118
- }
119
-
120
- /**
121
- * Application-wide state and state functions
122
- */
123
- const store = useMemo(() => ({
124
- ...state,
125
- sdk,
126
- fetchMessages,
127
- setMessages,
128
- onLiveChatRecovered,
129
- onAssignedAgentChanged,
130
- onAgentTypingStarted,
131
- onAgentTypingEnded,
132
- onMessageCreated,
133
- onContactStatusChanged
134
- }))
135
-
136
- return (
137
- <SdkContext.Provider value={store}>
138
- {children}
139
- </SdkContext.Provider>
140
- )
141
- }
@@ -1,45 +0,0 @@
1
- import { transformMessages, transformMessage } from '../../lib/transform-messages'
2
-
3
- const setMessages = (state, payload) => {
4
- return {
5
- ...state,
6
- messages: transformMessages(payload).reverse()
7
- }
8
- }
9
-
10
- const setMessage = (state, payload) => {
11
- return {
12
- ...state,
13
- message: transformMessage(payload),
14
- messages: [...state.messages, transformMessage(payload)]
15
- }
16
- }
17
-
18
- const setAgent = (state, payload) => {
19
- return {
20
- ...state,
21
- agent: payload
22
- }
23
- }
24
-
25
- const setAgentIsTyping = (state, payload) => {
26
- return {
27
- ...state,
28
- isAgentTyping: payload
29
- }
30
- }
31
-
32
- const setAgentStatus = (state, payload) => {
33
- return {
34
- ...state,
35
- agentStatus: payload
36
- }
37
- }
38
-
39
- export const actionsMap = {
40
- SET_MESSAGE: setMessage,
41
- SET_MESSAGES: setMessages,
42
- SET_AGENT: setAgent,
43
- SET_AGENT_TYPING: setAgentIsTyping,
44
- SET_AGENT_STATUS: setAgentStatus
45
- }
@@ -1,21 +0,0 @@
1
- import { actionsMap } from './actions-map'
2
-
3
- export const initialState = {
4
- messages: [],
5
- agent: null,
6
- agentStatus: null,
7
- isAgentTyping: false
8
- }
9
-
10
- export const reducer = (state, action) => {
11
- const { type, payload } = action
12
-
13
- const fn = actionsMap[type]
14
-
15
- if (fn) {
16
- const actionFunction = fn.bind(this, state, payload)
17
- return actionFunction()
18
- }
19
-
20
- return state
21
- }
@@ -1,5 +0,0 @@
1
- import { useContext } from 'react'
2
-
3
- import { SdkContext } from './SdkProvider.jsx'
4
-
5
- export const useSdk = () => useContext(SdkContext)
File without changes