{"id":29228,"date":"2026-06-21T14:41:45","date_gmt":"2026-06-21T14:41:45","guid":{"rendered":"https:\/\/mosaicconnect.io\/?page_id=29228"},"modified":"2026-06-21T14:42:44","modified_gmt":"2026-06-21T14:42:44","slug":"consultation","status":"publish","type":"page","link":"https:\/\/mosaicconnect.io\/en\/consultation\/","title":{"rendered":"Consultation"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"29228\" class=\"elementor elementor-29228\" data-elementor-post-type=\"page\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-6fbac06 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"6fbac06\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-09f8e4a\" data-id=\"09f8e4a\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-34d9cd1 elementor-widget elementor-widget-shortcode\" data-id=\"34d9cd1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\">        <div id=\"mc-consultation-gGOJwQgH\" class=\"mc-consultation-wrap\" data-language=\"en\">\n            <div class=\"mc-consultation-card\">\n                <header class=\"mc-consultation-header\">\n                    <div>\n                        <h2 class=\"mc-consultation-title\">Consultation Chat<\/h2>\n                        <p class=\"mc-consultation-subtitle\">Share your idea, budget, and experience. After the first reply, the form disappears and the chat continues with the same context.<\/p>\n                    <\/div>\n                <\/header>\n\n                <section class=\"mc-consultation-form-section\">\n                    <form class=\"mc-consultation-form\" novalidate>\n                        <div class=\"mc-consultation-grid\">\n                            <div class=\"mc-consultation-field mc-consultation-field-full\">\n                                <label for=\"mc-consultation-gGOJwQgH-idea\">Idea <span class=\"required\">*<\/span><\/label>\n                                <textarea id=\"mc-consultation-gGOJwQgH-idea\" name=\"idea\" rows=\"5\" required placeholder=\"Briefly describe what you want to build\"><\/textarea>\n                            <\/div>\n\n                            <div class=\"mc-consultation-field\">\n                                <label for=\"mc-consultation-gGOJwQgH-budget\">Budget <span class=\"required\">*<\/span><\/label>\n                                <input id=\"mc-consultation-gGOJwQgH-budget\" type=\"text\" name=\"budget\" required placeholder=\"1000\">\n                            <\/div>\n\n                            <div class=\"mc-consultation-field\">\n                                <label for=\"mc-consultation-gGOJwQgH-experience\">Years of experience <span class=\"required\">*<\/span><\/label>\n                                <input id=\"mc-consultation-gGOJwQgH-experience\" type=\"text\" name=\"experience\" required placeholder=\"10 years\">\n                            <\/div>\n                        <\/div>\n\n                        <div class=\"mc-consultation-actions\">\n                            <button type=\"submit\" class=\"mc-consultation-submit\">Start Chat<\/button>\n                        <\/div>\n\n                        <div class=\"mc-consultation-message\" aria-live=\"polite\"><\/div>\n                    <\/form>\n                <\/section>\n\n                <section class=\"mc-consultation-chat-section\" hidden>\n                    <div class=\"mc-consultation-summary\">\n                        <div class=\"mc-consultation-summary-title\">Submitted details<\/div>\n                        <div class=\"mc-consultation-summary-grid\">\n                            <div><span>Idea<\/span><strong data-summary=\"idea\"><\/strong><\/div>\n                            <div><span>Budget<\/span><strong data-summary=\"budget\"><\/strong><\/div>\n                            <div><span>Years of experience<\/span><strong data-summary=\"experience\"><\/strong><\/div>\n                        <\/div>\n                    <\/div>\n\n                    <div class=\"mc-consultation-chat\">\n                        <div class=\"mc-consultation-chat-header\">Chat<\/div>\n                        <div class=\"mc-consultation-messages\" data-panel=\"messages\" aria-live=\"polite\"><\/div>\n\n                        <div class=\"mc-consultation-composer\">\n                            <input type=\"text\" name=\"chatMessage\" placeholder=\"Type your message...\">\n                            <button type=\"button\" class=\"mc-consultation-chat-send\">Send<\/button>\n                        <\/div>\n\n                        <div class=\"mc-consultation-actions is-chat\">\n                            <button type=\"button\" class=\"mc-consultation-reset\">Start over<\/button>\n                        <\/div>\n\n                        <div class=\"mc-consultation-message is-chat-message\" aria-live=\"polite\"><\/div>\n                    <\/div>\n                <\/section>\n            <\/div>\n        <\/div>\n\n        <script>\n        (function(){\n            var wrap = document.getElementById(\"mc-consultation-gGOJwQgH\");\n            if (!wrap) return;\n\n            var formSection = wrap.querySelector('.mc-consultation-form-section');\n            var chatSection = wrap.querySelector('.mc-consultation-chat-section');\n            var form = wrap.querySelector('.mc-consultation-form');\n            var formMessage = wrap.querySelector('.mc-consultation-form .mc-consultation-message');\n            var chatMessage = wrap.querySelector('.mc-consultation-chat .mc-consultation-message');\n            var submitButton = wrap.querySelector('.mc-consultation-submit');\n            var chatSendButton = wrap.querySelector('.mc-consultation-chat-send');\n            var resetButton = wrap.querySelector('.mc-consultation-reset');\n            var messagesPanel = wrap.querySelector('[data-panel=\"messages\"]');\n            var summaryIdea = wrap.querySelector('[data-summary=\"idea\"]');\n            var summaryBudget = wrap.querySelector('[data-summary=\"budget\"]');\n            var summaryExperience = wrap.querySelector('[data-summary=\"experience\"]');\n            var chatInput = wrap.querySelector('input[name=\"chatMessage\"]');\n            var ajaxUrl = \"https:\\\/\\\/mosaicconnect.io\\\/wp-admin\\\/admin-ajax.php\";\n            var nonce = \"3713a0598f\";\n            var noncePromise = null;\n            var context = {\n                source: 'form',\n                requestId: '',\n                idea: '',\n                budget: '',\n                experience: ''\n            };\n\n            if (!form || !submitButton || !chatSection || !formSection || !messagesPanel || !chatInput || !chatSendButton || !resetButton) return;\n\n            var copy = {\"title\":\"Consultation Chat\",\"subtitle\":\"Share your idea, budget, and experience. After the first reply, the form disappears and the chat continues with the same context.\",\"idea_label\":\"Idea\",\"idea_placeholder\":\"Briefly describe what you want to build\",\"budget_label\":\"Budget\",\"budget_placeholder\":\"1000\",\"experience_label\":\"Years of experience\",\"experience_placeholder\":\"10 years\",\"submit_button\":\"Start Chat\",\"chat_title\":\"Chat\",\"chat_placeholder\":\"Type your message...\",\"chat_button\":\"Send\",\"reset_button\":\"Start over\",\"summary_title\":\"Submitted details\",\"form_required\":\"Please fill in idea, budget, and experience.\",\"chat_required\":\"Please type a message before sending.\",\"response_fallback\":\"Thanks. The chat is ready now.\",\"network_error\":\"Network error. Please try again.\",\"loading\":\"Sending...\",\"ready_state\":\"The form is hidden and the conversation continues below.\"};\n\n            function refreshNonce() {\n                if (noncePromise) return noncePromise;\n\n                noncePromise = fetch(ajaxUrl, {\n                    method: 'POST',\n                    headers: {'Content-Type': 'application\/x-www-form-urlencoded; charset=UTF-8'},\n                    body: new URLSearchParams({ action: 'mc_consultation_get_nonce' }).toString(),\n                    credentials: 'same-origin'\n                })\n                .then(function(res){ return res.json(); })\n                .then(function(resp){\n                    if (resp && resp.success && resp.data && resp.data.nonce) {\n                        nonce = resp.data.nonce;\n                        return nonce;\n                    }\n                    throw new Error('Could not load security token.');\n                })\n                .catch(function(err){\n                    noncePromise = null;\n                    throw err;\n                });\n\n                return noncePromise;\n            }\n\n            function prettyText(value) {\n                if (typeof value === 'string') return value;\n                try {\n                    return JSON.stringify(value, null, 2);\n                } catch (e) {\n                    return String(value);\n                }\n            }\n\n            function setStatus(text, isError, target) {\n                var box = target || formMessage;\n                if (!box) return;\n                box.classList.remove('is-error', 'is-success');\n                if (text) {\n                    box.classList.add(isError ? 'is-error' : 'is-success');\n                    box.textContent = text;\n                } else {\n                    box.textContent = '';\n                }\n            }\n\n            function createMessage(role, text) {\n                var item = document.createElement('div');\n                item.className = 'mc-consultation-message-item is-' + role;\n\n                var roleEl = document.createElement('div');\n                roleEl.className = 'mc-consultation-message-role';\n                roleEl.textContent = role === 'user' ? 'You' : role === 'system' ? 'System' : 'Assistant';\n\n                var bodyEl = document.createElement('div');\n                bodyEl.className = 'mc-consultation-message-body';\n                bodyEl.textContent = text;\n\n                item.appendChild(roleEl);\n                item.appendChild(bodyEl);\n                return item;\n            }\n\n            function clearMessages() {\n                while (messagesPanel.firstChild) {\n                    messagesPanel.removeChild(messagesPanel.firstChild);\n                }\n            }\n\n            function appendMessage(role, text) {\n                messagesPanel.appendChild(createMessage(role, text));\n                messagesPanel.scrollTop = messagesPanel.scrollHeight;\n            }\n\n            function syncSummary() {\n                if (summaryIdea) summaryIdea.textContent = context.idea;\n                if (summaryBudget) summaryBudget.textContent = context.budget;\n                if (summaryExperience) summaryExperience.textContent = context.experience;\n            }\n\n            function showChatState() {\n                formSection.hidden = true;\n                chatSection.hidden = false;\n                syncSummary();\n                if (!messagesPanel.childNodes.length) {\n                    appendMessage('system', copy.ready_state);\n                }\n                chatInput.focus();\n            }\n\n            function showFormState() {\n                chatSection.hidden = true;\n                formSection.hidden = false;\n                setStatus('', false, formMessage);\n                setStatus('', false, chatMessage);\n                submitButton.disabled = false;\n                submitButton.textContent = copy.submit_button;\n                chatSendButton.disabled = false;\n                chatSendButton.textContent = copy.chat_button;\n                form.reset();\n                chatInput.value = '';\n                context = { source: 'form', requestId: '', idea: '', budget: '', experience: '' };\n                clearMessages();\n                syncSummary();\n                form.querySelector('[name=\"idea\"]').focus();\n            }\n\n            function extractAssistantMessage(resp, fallback) {\n                if (resp && resp.data) {\n                    if (typeof resp.data.message === 'string' && resp.data.message.trim() !== '') {\n                        return resp.data.message;\n                    }\n                    if (typeof resp.data.webhook_response !== 'undefined') {\n                        return prettyText(resp.data.webhook_response);\n                    }\n                }\n                return fallback;\n            }\n\n            function buildBody(source, chatMessage) {\n                return new URLSearchParams({\n                    action: 'mc_consultation_submit',\n                    nonce: nonce,\n                    request_id: context.requestId,\n                    source: source,\n                    idea: context.idea,\n                    budget: context.budget,\n                    experience: context.experience,\n                    chatMessage: chatMessage || '',\n                    message_id: (typeof crypto !== 'undefined' && crypto.randomUUID)\n                        ? crypto.randomUUID()\n                        : ('msg-' + Date.now() + '-' + Math.random().toString(16).slice(2))\n                });\n            }\n\n            function submitToWebhook(source, chatText) {\n                var isChat = source === 'chat';\n                var button = isChat ? chatSendButton : submitButton;\n                var statusBox = isChat ? chatMessage : formMessage;\n                var fallbackMessage = isChat ? copy.response_fallback : copy.response_fallback;\n                var outgoingText = chatText || '';\n\n                button.disabled = true;\n                button.textContent = isChat ? copy.loading : copy.loading;\n                setStatus('', false, statusBox);\n\n                if (isChat) {\n                    appendMessage('user', outgoingText);\n                }\n\n                return refreshNonce()\n                    .then(function(){\n                        return fetch(ajaxUrl, {\n                            method: 'POST',\n                            headers: {'Content-Type': 'application\/x-www-form-urlencoded; charset=UTF-8'},\n                            body: buildBody(source, outgoingText).toString(),\n                            credentials: 'same-origin'\n                        });\n                    })\n                    .then(function(res){ return res.json(); })\n                    .then(function(resp){\n                        if (resp && resp.success && resp.data) {\n                            if (!isChat) {\n                                context.source = 'chat';\n                                if (resp.data.request_id) {\n                                    context.requestId = resp.data.request_id;\n                                }\n                                appendMessage('assistant', extractAssistantMessage(resp, fallbackMessage));\n                                showChatState();\n                            } else {\n                                appendMessage('assistant', extractAssistantMessage(resp, fallbackMessage));\n                            }\n                            setStatus('', false, statusBox);\n                            if (isChat) {\n                                chatInput.value = '';\n                            }\n                            return;\n                        }\n\n                        var err = (resp && resp.data && resp.data.message) ? resp.data.message : 'Submission failed.';\n                        setStatus(err, true, statusBox);\n                        if (isChat) {\n                            appendMessage('system', err);\n                        }\n                    })\n                    .catch(function(){\n                        var err = copy.network_error;\n                        setStatus(err, true, statusBox);\n                        if (isChat) {\n                            appendMessage('system', err);\n                        }\n                    })\n                    .finally(function(){\n                        button.disabled = false;\n                        button.textContent = isChat ? copy.chat_button : copy.submit_button;\n                    });\n            }\n\n            form.addEventListener('submit', function(e){\n                e.preventDefault();\n                context.idea = form.querySelector('[name=\"idea\"]').value.trim();\n                context.budget = form.querySelector('[name=\"budget\"]').value.trim();\n                context.experience = form.querySelector('[name=\"experience\"]').value.trim();\n                context.source = 'form';\n                context.requestId = (typeof crypto !== 'undefined' && crypto.randomUUID)\n                    ? crypto.randomUUID()\n                    : ('req-' + Date.now() + '-' + Math.random().toString(16).slice(2));\n\n                if (!context.idea || !context.budget || !context.experience) {\n                    setStatus(copy.form_required, true, formMessage);\n                    return;\n                }\n\n                submitToWebhook('form', '');\n            });\n\n            chatSendButton.addEventListener('click', function(){\n                var text = chatInput.value.trim();\n                if (!text) {\n                    setStatus(copy.chat_required, true, chatMessage);\n                    return;\n                }\n                submitToWebhook('chat', text);\n            });\n\n            chatInput.addEventListener('keydown', function(e){\n                if (e.key === 'Enter' && !e.shiftKey) {\n                    e.preventDefault();\n                    chatSendButton.click();\n                }\n            });\n\n            resetButton.addEventListener('click', function(){\n                showFormState();\n            });\n\n            syncSummary();\n        })();\n        <\/script>\n        <\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_joinchat":[],"footnotes":""},"class_list":["post-29228","page","type-page","status-publish","hentry"],"_hostinger_reach_plugin_has_subscription_block":false,"_hostinger_reach_plugin_is_elementor":false,"_links":{"self":[{"href":"https:\/\/mosaicconnect.io\/en\/wp-json\/wp\/v2\/pages\/29228","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mosaicconnect.io\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/mosaicconnect.io\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/mosaicconnect.io\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mosaicconnect.io\/en\/wp-json\/wp\/v2\/comments?post=29228"}],"version-history":[{"count":4,"href":"https:\/\/mosaicconnect.io\/en\/wp-json\/wp\/v2\/pages\/29228\/revisions"}],"predecessor-version":[{"id":29232,"href":"https:\/\/mosaicconnect.io\/en\/wp-json\/wp\/v2\/pages\/29228\/revisions\/29232"}],"wp:attachment":[{"href":"https:\/\/mosaicconnect.io\/en\/wp-json\/wp\/v2\/media?parent=29228"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}