UNPKG

@crazy-web/feedback

Version:

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

274 lines (273 loc) 16.1 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.submitIdea = exports.roadMapContainer = void 0; exports.renderFeedbacks = renderFeedbacks; const config_1 = require("../core/lib/config"); const enum_1 = require("../core/lib/enum"); const fetchRoadMaps_1 = require("../core/usecases/fetchRoadMaps"); const handleSubmit_1 = require("../core/usecases/handleSubmit"); const feedbackDetails_1 = require("./feedbackDetails"); const ideas_1 = require("./ideas"); const checkIsDarkMode_1 = require("./reuseables/checkIsDarkMode"); const featureCard_1 = require("./reuseables/featureCard"); const roadMapContainer = (data, selectedCard) => __awaiter(void 0, void 0, void 0, function* () { const { orgData, form, config } = data; const { primaryColor = config_1.configData === null || config_1.configData === void 0 ? void 0 : config_1.configData.primaryColor, heading = config_1.configData.heading, theme = config_1.configData === null || config_1.configData === void 0 ? void 0 : config_1.configData.theme } = config !== null && config !== void 0 ? config : {}; const isDarkMode = (0, checkIsDarkMode_1.checkIsDarkMode)({ theme }); const accountId = orgData === null || orgData === void 0 ? void 0 : orgData.organizationId; const websiteId = orgData === null || orgData === void 0 ? void 0 : orgData.websiteId; const container = document.createElement("div"); container.className = "prodio-feedback-hidden-scrollbar"; // container.style.cssText = "display:flex;flex-direction:column;gap:15px;overflow-y:auto;padding:1px;height:500px"; container.style.overflowY = "auto"; container.style.display = "flex"; container.style.flexDirection = "column"; container.style.gap = "15px"; container.style.padding = "1px"; container.style.height = "calc(100vh - 190px)"; const ideaForm = document.createElement("div"); ideaForm.innerHTML = (0, ideas_1.renderIdeaForm)(data); container.appendChild(ideaForm); const prodioTabContent = document.getElementById("prodio-tab-content"); prodioTabContent === null || prodioTabContent === void 0 ? void 0 : prodioTabContent.appendChild(container); const fields = ["slider-title", "slider-type", "slider-description"]; fields.forEach((field) => { const input = document.getElementById(field); const label = document.querySelector(`label[for="${field}"]`); if (input && label) { input.addEventListener("focus", () => { label.style.color = primaryColor; input.style.outline = "none"; // Removes focus outline input.style.border = "none"; // Removes border }); input.addEventListener("blur", () => { label.style.color = "black"; input.style.border = "none"; // Ensure border stays removed after blur }); } }); renderFeedbacks(accountId, websiteId, false, primaryColor, isDarkMode); // to submit the ideas (0, exports.submitIdea)({ orgData, primaryColor, isDarkMode }); // ✅to manage the submit a new idea button (0, ideas_1.manageSubmitANewIdeaButton)(); // to manage click on the ideas feedback card (0, feedbackDetails_1.onFeedbackCardClick)(selectedCard, data, primaryColor, isDarkMode); }); exports.roadMapContainer = roadMapContainer; function renderFeedbacks(accountId_1, websiteId_1) { return __awaiter(this, arguments, void 0, function* (accountId, websiteId, resetData = false, primaryColor, isDarkMode) { const container = document.querySelector(".prodio-feedback-hidden-scrollbar"); const feedbackContainer = document.getElementById("feedback-list"); if (!feedbackContainer) return; // Clear existing content if resetData is true if (resetData) { feedbackContainer.innerHTML = ""; } // Show loading spinner const spinner = document.createElement("div"); spinner.classList.add("spinner"); spinner.innerHTML = ` <div class="prodio-spinner-container"> <div class="prodio-spinner"></div> </div> `; feedbackContainer.appendChild(spinner); const { data } = yield (0, fetchRoadMaps_1.fetchRoadMaps)({ organizationId: accountId, websiteId }); feedbackContainer.innerHTML = ""; // Remove spinner after loading feedbackContainer.style.display = "flex"; feedbackContainer.style.flexDirection = "column"; feedbackContainer.style.gap = "15px"; const borderColor = isDarkMode ? "1px solid #292B2F" : "1px solid #31333740"; const headerColor = isDarkMode ? "#D2D3E0" : "#303540"; const counterBackgroundColor = isDarkMode ? "#FFFFFFD9" : "#1F2026D9"; const counterTextColor = isDarkMode ? "#1F2026" : "#F8F9FA"; // Render accordions data.forEach((section, index) => { var _a, _b, _c, _d, _e, _f; // Create accordion container const accordion = document.createElement("div"); accordion.classList.add("accordion"); accordion.style.border = borderColor; // accordion.style.borderTop = `2px solid ${FeedbackStatus[section?.status]?.color}` // accordion.style.boxShadow = "0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24)" accordion.style.borderRadius = "8px"; // Create status (accordion header) const statusHeader = document.createElement("div"); statusHeader.classList.add("accordion-header"); // <span style="width: 8px; height: 8px; border-radius: 50%; background-color:${FeedbackStatus[section?.status]?.color}; display: inline-block;"></span> statusHeader.innerHTML = ` <div style="display: flex; align-items: center; gap: 6px;"> <span style="font-size: 15px; color:${headerColor}; font-weight: 600;"> ${(_a = enum_1.FeedbackStatus[section === null || section === void 0 ? void 0 : section.status]) === null || _a === void 0 ? void 0 : _a.label} </span> ${((_b = section === null || section === void 0 ? void 0 : section.data) === null || _b === void 0 ? void 0 : _b.length) > 0 ? `<span style=" background-color:${counterBackgroundColor}; color:${counterTextColor}; padding: 2px 6px; border-radius:8px; font-size: 12px; font-weight: 500; margin-left: 15px; " > ${(_c = section === null || section === void 0 ? void 0 : section.data) === null || _c === void 0 ? void 0 : _c.length} ${((_d = section === null || section === void 0 ? void 0 : section.data) === null || _d === void 0 ? void 0 : _d.length) === 1 ? "Item" : "Items"} </span>` : ``} </div> `; statusHeader.style.cursor = "pointer"; statusHeader.style.fontSize = "16px"; statusHeader.style.padding = "10px 20px"; statusHeader.style.display = "flex"; statusHeader.style.justifyContent = "space-between"; statusHeader.style.alignItems = "center"; statusHeader.style.zIndex = "99999999"; statusHeader.style.borderBottom = borderColor; // Add arrow icon const arrow = document.createElement("span"); arrow.innerHTML = renderAccordionCloseIcon({ stroke: headerColor }); // Closed state statusHeader.appendChild(arrow); // Create content container const content = document.createElement("div"); content.classList.add("accordion-content"); content.style.display = "block"; // content.style.border = "1px solid #ddd"; // content.style.borderTop = "none"; content.style.marginBottom = "10px"; // Render cards if (((_e = section === null || section === void 0 ? void 0 : section.data) === null || _e === void 0 ? void 0 : _e.length) > 0) { (_f = section === null || section === void 0 ? void 0 : section.data) === null || _f === void 0 ? void 0 : _f.forEach((item, idx) => { const card = document.createElement("div"); card.innerHTML = (0, featureCard_1.FeatureCards)(item, idx, "card", primaryColor, 2, isDarkMode); card.setAttribute("data-feedback", JSON.stringify(item)); card.setAttribute("data-feedback-id", item === null || item === void 0 ? void 0 : item.id); content.appendChild(card); }); } else { content.innerHTML = `<div class="prodio-no-data">No ideas found.</div>`; } // Toggle accordion on click statusHeader.addEventListener("click", () => { const isOpen = content.style.display === "block"; statusHeader.style.borderBottom = !isOpen ? borderColor : "none"; // Toggle border content.style.display = isOpen ? "none" : "block"; arrow.innerHTML = !isOpen ? renderAccordionCloseIcon({ stroke: headerColor }) : renderAccordionOpenIcon({ stroke: headerColor }); // Toggle arrow }); // Prevent event bubbling when clicking the arrow arrow.addEventListener("click", (event) => { event.stopPropagation(); // Stop the event from reaching statusHeader const isOpen = content.style.display === "block"; content.style.display = isOpen ? "none" : "block"; arrow.innerHTML = !isOpen ? renderAccordionCloseIcon({ stroke: headerColor }) : renderAccordionOpenIcon({ stroke: headerColor }); // Toggle arrow }); // Append elements accordion.appendChild(statusHeader); accordion.appendChild(content); feedbackContainer.appendChild(accordion); }); }); } const submitIdea = ({ orgData, primaryColor, isDarkMode }) => { var _a; const inputs = [ document.getElementById("slider-type"), document.getElementById("slider-title"), document.getElementById("slider-description") ]; inputs.forEach(input => { input.addEventListener("input", () => { input.style.border = "none"; document.getElementById("slider-error").style.display = "none"; }); }); (_a = document.getElementById("slider-submit")) === null || _a === void 0 ? void 0 : _a.addEventListener("click", () => __awaiter(void 0, void 0, void 0, function* () { var _a, _b, _c; const submitButton = document.getElementById("slider-submit"); const type = document.getElementById("slider-type").value; const title = document.getElementById("slider-title").value; const description = document.getElementById("slider-description").value; const accountId = orgData === null || orgData === void 0 ? void 0 : orgData.organizationId; const websiteId = orgData; // let hasError = false; // inputs.forEach(input => { // if (!input.value.trim()) { // input.style.border = "1px solid red"; // hasError = true; // } // }); // if (hasError) { // document.getElementById("slider-error")!.style.display = "block"; // return; // } if (!title.trim() || !description.trim()) { document.getElementById("slider-error").style.display = "block"; return; } submitButton.disabled = true; submitButton.classList.add("prodio-disabled-btn"); 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: "", source: { id: website, name: "slider", //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, // false website_id: orgData === null || orgData === void 0 ? void 0 : orgData.websiteId, submission_mode: enum_1.SubmissionMode.feedback }; const res = yield (0, handleSubmit_1.handleSubmit)(dataToSend); if (res.error) { document.getElementById("slider-error").textContent = res.error; document.getElementById("slider-error").style.display = "block"; } else { renderFeedbacks(accountId, websiteId, true, primaryColor, isDarkMode); document.getElementById("slider-title").value = ""; document.getElementById("slider-description").value = ""; } submitButton.disabled = false; submitButton.classList.remove("prodio-disabled-btn"); })); }; exports.submitIdea = submitIdea; const renderAccordionCloseIcon = ({ stroke }) => { return ` <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke=${stroke} stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down"><path d="m6 9 6 6 6-6"/></svg> `; // return ` // <svg width="15px" height="15px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg" fill=${stroke}><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M903.232 768l56.768-50.432L512 256l-448 461.568 56.768 50.432L512 364.928z" fill=${stroke}></path></g></svg> // ` }; const renderAccordionOpenIcon = ({ stroke }) => { // return ` // <svg width="15px" height="15px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg" fill=${stroke}><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M903.232 256l56.768 50.432L512 768 64 306.432 120.768 256 512 659.072z" fill=${stroke}></path></g></svg> // ` return ` <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke=${stroke} stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-right-icon lucide-chevron-right"><path d="m9 18 6-6-6-6"/></svg> `; };