UNPKG

@crazy-web/feedback

Version:

A feedback form handler package that shows a popup based on allowed URLs.

252 lines (244 loc) 11.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.showPopup = showPopup; const __1 = require(".."); const enum_1 = require("../core/lib/enum"); const Storage_1 = require("../core/repositories/Storage"); const handleSubmit_1 = require("../core/usecases/handleSubmit"); const whiteLabel_1 = require("./whiteLabel"); /** * Displays a feedback popup with form fields. */ function showPopup(matchedOrg) { if (document.getElementById("custom-popup-overlay")) return; // Avoid duplicate popups const { id, metadata } = matchedOrg; const { frequency, openAfter = 0, form, whiteLabel = false } = metadata; const { title = "Submit your feedback", description = "Fill out the form below to submit you feedback", theme = "system", primaryColor = "#39C3EF" } = form; // Set theme-based styles const isDarkMode = theme === "dark" || (theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches); const backgroundColor = isDarkMode ? "#000" : "#fff"; const textColor = isDarkMode ? "#fff" : "#000"; const borderColor = isDarkMode ? "#6a676778" : "#868484"; const labelColor = isDarkMode ? "#bbb" : "#000"; // Create the overlay const overlay = document.createElement("div"); overlay.id = "custom-popup-overlay"; overlay.style.position = "fixed"; overlay.style.top = "0"; overlay.style.left = "0"; overlay.style.width = "100%"; overlay.style.height = "100%"; overlay.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; overlay.style.zIndex = "9999998"; // Create the popup container const popup = document.createElement("div"); popup.id = "custom-popup"; popup.style.display = "flex"; popup.style.flexDirection = "column"; popup.style.gap = "12px"; popup.style.position = "fixed"; popup.style.zIndex = "9999999"; popup.style.top = "50%"; popup.style.left = "50%"; popup.style.transform = "translate(-50%, -50%)"; popup.style.backgroundColor = backgroundColor; popup.style.color = textColor; popup.style.padding = "20px"; popup.style.borderRadius = "10px"; popup.style.width = "90%"; popup.style.maxWidth = "400px"; // popup.style.border = `1px solid ${textColor}`; popup.style.boxShadow = '0 0 15px rgba(0,0,0,0.2)'; const renderWhiteLabel = () => { if (!whiteLabel) { return `${(0, whiteLabel_1.whiteLabelRender)({})}`; // return `<a style="font-size:9px;color:#39C3EF;text-align:right;text-decoration:none;" href="https://prodio.app" target="_blank">Powered by Prodio</a>` } else { return `<span style="display:none;"></span>`; } }; // Function to add styles dynamically without using an ID const addStyles = () => { const styleElement = document.createElement("style"); styleElement.innerHTML = ` .prodio-feedback-form-heading { font-size: 27px; margin: 0; } @media screen and (max-width: 700px) { .prodio-feedback-form-heading { font-size: 20px; } } .prodio-feedback-form-description { font-size: 14px; } @media screen and (max-width: 700px) { .prodio-feedback-form-description { font-size: 12px; } } `; document.head.appendChild(styleElement); }; // Function to remove styles without using an ID const removeStyles = () => { const styles = document.head.getElementsByTagName("style"); for (let i = 0; i < styles.length; i++) { if (styles[i].innerHTML.includes(".prodio-feedback")) { styles[i].remove(); break; } } }; popup.innerHTML = ` <h2 class="prodio-feedback-form-heading">${title}</h2> <span class="prodio-feedback-form-description">${description}</span> <div style="display: flex; flex-direction: column; gap: 8px; width: 100%;"> <label for="popup-type" style="display: block; text-align: left; color: ${labelColor};font-size:12px;">Type *</label> <select id="popup-type" style="padding: 6px 8px;font-size:14px; border-radius: 5px; border: 1px solid ${borderColor}; background: ${backgroundColor}; color: ${textColor};"> <option value="feature">Feature</option> <option value="bug">Bug</option> <option value="improvement">Improvement</option> <option value="task">Task</option> <option value="question">Question</option> </select> </div> <div style="display: flex; flex-direction: column; gap: 8px; width: 100%;"> <label for="popup-title" style="display: block; text-align: left; color:${labelColor};font-size:12px;">Title *</label> <input type="text" id="popup-title" placeholder="Enter title" autocomplete="off" style="padding: 6px 8px;font-size:14px; border-radius: 5px; border: 1px solid ${borderColor}; background: ${backgroundColor}; color: ${textColor};" /> </div> <div style="display: flex; flex-direction: column; gap: 8px; width: 100%;"> <label for="popup-description" style="display: block; text-align: left; color:${labelColor};font-size:12px;">Description *</label> <textarea id="popup-description" placeholder="Enter description" autocomplete="off" rows="5" style="padding: 6px 8px;font-size:14px; border-radius: 5px; border: 1px solid ${borderColor}; background: ${backgroundColor}; color: ${textColor}; resize: none;" ></textarea> </div> <span id="popup-error" style="color: red; display: none; font-size:12px;">All fields are required</span> <div style="display: flex;justify-content: end;gap: 12px;"> <button id="popup-close" style="padding: 5px 20px; background-color: ${backgroundColor}; border: 1px solid ${textColor}; border-radius: 5px; color: ${textColor}; font-size: 14px; cursor: pointer;"> Cancel </button> <button id="popup-submit" style="padding: 5px 20px; background-color: ${primaryColor}; border: none; border-radius: 5px; color: #fff; font-size: 14px; cursor: pointer;"> Submit </button> </div> ${renderWhiteLabel()} `; // Show popup after delay setTimeout(() => { addStyles(); // Add styles before showing popup document.body.appendChild(overlay); document.body.appendChild(popup); document.body.style.overflow = "hidden"; const errorSpan = document.getElementById("popup-error"); const inputs = [ document.getElementById("popup-type"), document.getElementById("popup-title"), document.getElementById("popup-description") ]; inputs.forEach(input => { input.addEventListener("input", () => { input.style.border = `1px solid ${borderColor}`; errorSpan.style.display = "none"; }); }); const orgData = (0, Storage_1.getFromSessionStorage)(__1.SessionStorageName); // Submit button click handler document.getElementById("popup-submit").addEventListener("click", () => { var _a, _b, _c; const type = document.getElementById("popup-type").value; const title = document.getElementById("popup-title").value; const description = document.getElementById("popup-description").value; let hasError = false; inputs.forEach(input => { if (!input.value.trim()) { input.style.border = "1px solid red"; hasError = true; } }); if (hasError) { errorSpan.style.display = "block"; return; } const website = window.location.hostname; const dataToSend = { title: title, description: description !== null && description !== void 0 ? description : "", type: type, // How we will define its a type of feature, tasks, or bug, we can add more types here. feedback_id: id, source: { id: website, name: "popup", type: "Website", }, user_id: (_a = orgData === null || orgData === void 0 ? void 0 : orgData.userData) === null || _a === void 0 ? void 0 : _a.id, user_name: (_b = orgData === null || orgData === void 0 ? void 0 : orgData.userData) === null || _b === void 0 ? void 0 : _b.name, user_email: (_c = orgData === null || orgData === void 0 ? void 0 : orgData.userData) === null || _c === void 0 ? void 0 : _c.email, created_at: new Date(), updated_at: new Date(), last_retrieved_message: false, account_id: orgData === null || orgData === void 0 ? void 0 : orgData.organizationId, meta_data: null, is_public: false, website_id: orgData === null || orgData === void 0 ? void 0 : orgData.websiteId, submission_mode: enum_1.SubmissionMode.feedback }; (0, handleSubmit_1.handleSubmit)(dataToSend).then((res) => { var _a; if (res.error) { // sho red error errorSpan.textContent = res.error; errorSpan.style.display = "block"; } else { popup.innerHTML = ` <h2 class="prodio-feedback-form-heading" style="text-align:center;">Thank you for your feedback</h2> <div style="display:flex;justify-content:center;margin-top:20px;"> <button id="done-button" style="padding: 5px 20px; background-color: ${primaryColor}; border: none; border-radius: 5px; color: #fff; font-size: 14px; cursor: pointer;"> Done </button> </div> `; document.getElementById("done-button").addEventListener("click", () => { overlay.remove(); popup.remove(); document.body.style.overflow = ""; removeStyles(); }); const submittedForms = (_a = orgData === null || orgData === void 0 ? void 0 : orgData.submittedForms) !== null && _a !== void 0 ? _a : []; submittedForms.push(id); (0, Storage_1.saveToSessionStorage)(__1.SessionStorageName, Object.assign(Object.assign({}, orgData), { submittedForms })); // saveToLocalStorage(localStorageName,{submittedForms:submittedForms}) // res.message // show form submitted successfully popup } }); }); // Close button click handler document.getElementById("popup-close").addEventListener("click", () => { var _a; overlay.remove(); popup.remove(); if (frequency === __1.frequencyTypes.everySession) { const submittedForms = (_a = orgData === null || orgData === void 0 ? void 0 : orgData.submittedForms) !== null && _a !== void 0 ? _a : []; submittedForms.push(id); (0, Storage_1.saveToSessionStorage)(__1.SessionStorageName, Object.assign(Object.assign({}, orgData), { submittedForms })); } document.body.style.overflow = ""; // Re-enable scrolling removeStyles(); // Remove styles after closing popup }); }, openAfter * 1000); // Convert seconds to milliseconds }