@afex-bots/feedback
Version:
Feedback Bot
1,290 lines (1,258 loc) • 43.3 kB
JavaScript
// src/components/bot/bot.module.css
var bot_default = {
dialogContainer: "bot_dialogContainer",
dialogContent: "bot_dialogContent"
};
// src/components/bot/index.tsx
import {
ActionIcon as ActionIcon2,
Box,
deepMerge,
Dialog,
MantineProvider,
Stack as Stack3,
Text as Text6
} from "@mantine/core";
import { useState as useState6 } from "react";
// src/libs/config.tsx
import { Home3, MessageQuestion, Messages1 } from "iconsax-react";
import { jsx } from "react/jsx-runtime";
var defaultPosition = "bottom-right";
var defaultSections = [
{
icon: /* @__PURE__ */ jsx(Home3, { color: "#948A8A", size: "20" }),
id: "Home",
title: "Home"
},
{
icon: /* @__PURE__ */ jsx(MessageQuestion, { color: "#948A8A", size: "20" }),
id: "Issue",
title: "Report an Issue"
},
{
icon: /* @__PURE__ */ jsx(Messages1, { color: "#948A8A", size: "20" }),
id: "Chat",
title: "Live Chat"
}
];
var defaultSupportGuide = {
gradient: ["#ff9e9988", "white"],
system: "Exchange",
titles: [
{
description: "getting started AFEX System",
guideSections: [
{
heading: "Step 1: Download the App",
steps: [
"Head to your app store (Google Play Store or Apple App Store) and search for [App Name].",
"Tap the Install button and wait for the app to download."
]
},
{
heading: "Step 2: Download the App",
steps: [
"Open the app and tap on Sign Up.",
"Provide your details such as name, email, and a secure password."
]
}
],
heading: "Getting Started with AFEX System",
id: 1
}
]
};
var defaultConfiguration = {
position: defaultPosition,
sections: defaultSections,
supportGuide: defaultSupportGuide,
icon: /* @__PURE__ */ jsx(MessageQuestion, { color: "#FFFFFF", size: 20, variant: "Bold" })
};
// src/types/index.ts
var View = Object.freeze({
Chat: "Chat",
Feedback: "Feedback",
Home: "Home",
Info: "Info",
Issue: "Issue"
});
// src/components/bot/index.tsx
import { useClickOutside } from "@mantine/hooks";
// src/components/faqs/faqs.module.css
var faqs_default = {
container: "faqs_container",
logo: "faqs_logo",
heading: "faqs_heading",
faqBox: "faqs_faqBox",
inputWrapper: "faqs_inputWrapper",
inputInner: "faqs_inputInner",
supportItem: "faqs_supportItem",
feedbackLink: "faqs_feedbackLink"
};
// src/components/faqs/index.tsx
import { Text, Input } from "@mantine/core";
import { ArrowRight2, SearchNormal1 } from "iconsax-react";
import { useState } from "react";
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
var SupportItem = ({ title, onClick }) => /* @__PURE__ */ jsxs("button", { type: "button", onClick, className: faqs_default.supportItem, children: [
title,
" ",
/* @__PURE__ */ jsx2(ArrowRight2, { size: "22", color: "#292D32" })
] });
var FeedbackLink = ({ system, onClick }) => /* @__PURE__ */ jsxs("button", { type: "button", onClick, className: faqs_default.feedbackLink, children: [
"Give ",
system,
" feedback",
/* @__PURE__ */ jsx2(Text, { fz: "md", fw: "normal", children: "Kindly fill the feedback form so we can understand how to serve you better." })
] });
var Support = ({ supportGuide, navigate }) => {
const [searchTerm, setSearchTerm] = useState("");
const filteredFaqs = supportGuide?.titles?.filter(
(item) => item.heading.toLowerCase().includes(searchTerm.toLowerCase())
);
return /* @__PURE__ */ jsxs("div", { className: faqs_default.container, children: [
/* @__PURE__ */ jsxs(
"svg",
{
width: "65",
height: "20",
viewBox: "0 0 65 20",
fill: "none",
xmlns: "http://www.w3.org/2000/svg",
children: [
/* @__PURE__ */ jsx2("title", { children: "AFEXLogo" }),
/* @__PURE__ */ jsx2(
"path",
{
d: "M33.1885 0.878906V19.153H45.6607V16.2521H36.3844V11.3517H45.0543V8.45079H36.3844V3.77982H45.6607V0.878906H33.1885Z",
fill: "#202020"
}
),
/* @__PURE__ */ jsx2(
"path",
{
d: "M19.8965 0.878906V19.153H23.1088V11.3517H31.7787V8.45079H23.1088V3.77982H32.3851V0.878906H19.8965Z",
fill: "#202020"
}
),
/* @__PURE__ */ jsx2(
"path",
{
d: "M53.6258 10.0084L46.4473 19.1536H50.6429L55.7072 12.6962L60.7715 19.1536H64.9672C63.4102 17.1705 57.1167 9.15613 55.6908 7.33691L53.593 10.0084H53.6258Z",
fill: "#E1261C"
}
),
/* @__PURE__ */ jsx2(
"path",
{
d: "M55.7238 7.3363L53.626 10.0078L46.4639 0.878906H50.6595L55.7238 7.3363Z",
fill: "#202020"
}
),
/* @__PURE__ */ jsx2(
"path",
{
d: "M65 0.878906L57.8215 10.0078L55.7236 7.3363L60.8043 0.878906H65Z",
fill: "#202020"
}
),
/* @__PURE__ */ jsx2(
"path",
{
d: "M7.80131 0.845703L0 19.1526H3.40898L9.55498 4.71358L12.3739 11.3512H8.63717L7.44075 14.1702H13.5867L15.701 19.1526H19.1099L11.3086 0.845703H7.80131Z",
fill: "#202020"
}
)
]
}
),
/* @__PURE__ */ jsxs("h1", { className: faqs_default.heading, children: [
"Welcome to ",
supportGuide?.system
] }),
supportGuide?.customFaqSection ?? /* @__PURE__ */ jsxs("div", { className: faqs_default.faqBox, children: [
/* @__PURE__ */ jsx2(
Input,
{
classNames: {
wrapper: faqs_default.inputWrapper,
input: faqs_default.inputInner
},
rightSection: /* @__PURE__ */ jsx2(SearchNormal1, { size: 20, color: "#292D32" }),
placeholder: "Search for help...",
value: searchTerm,
onChange: (e) => setSearchTerm(e.currentTarget.value)
}
),
filteredFaqs?.length ? filteredFaqs.map((item, index) => /* @__PURE__ */ jsx2(
SupportItem,
{
title: item.heading,
id: item.id ?? index,
onClick: () => navigate("support-info", item.id ?? index)
},
item.id ?? index
)) : /* @__PURE__ */ jsx2(Text, { fz: "sm", c: "dimmed", mt: "sm", children: "No results found." })
] }),
/* @__PURE__ */ jsx2(
FeedbackLink,
{
system: supportGuide?.system,
onClick: () => navigate("feed-back-form")
}
)
] });
};
// src/components/faqs/info/info.module.css
var info_default = {
container: "info_container",
backIcon: "info_backIcon",
title: "info_title",
subtitle: "info_subtitle",
contentWrapper: "info_contentWrapper",
noInfoText: "info_noInfoText"
};
// src/components/faqs/info/index.tsx
import { ArrowLeft2 } from "iconsax-react";
import { List, Stack, Text as Text2 } from "@mantine/core";
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
var SupportInfo = ({ lists, onBack, title }) => {
return /* @__PURE__ */ jsxs2("div", { className: info_default.container, children: [
/* @__PURE__ */ jsx3(
ArrowLeft2,
{
color: "#292D32",
size: 35,
onClick: onBack,
className: info_default.backIcon
}
),
/* @__PURE__ */ jsx3("h3", { className: info_default.title, children: title }),
/* @__PURE__ */ jsxs2("p", { className: info_default.subtitle, children: [
"Welcome to ",
title,
"! Let\u2019s get you set up and ready to explore all the amazing features we have to offer."
] }),
/* @__PURE__ */ jsxs2("div", { className: info_default.contentWrapper, children: [
/* @__PURE__ */ jsx3(Text2, { className: info_default.noInfoText, children: "No setup information available." }),
lists.map((section) => /* @__PURE__ */ jsxs2(Stack, { children: [
/* @__PURE__ */ jsx3(Text2, { fw: "bold", children: section.heading }),
/* @__PURE__ */ jsx3(List, { listStyleType: "disc", children: section.steps.map((step) => /* @__PURE__ */ jsx3(List.Item, { children: step }, step)) })
] }, section.heading))
] })
] });
};
// src/components/form/feed-back-form/feed-back-form.module.css
var feed_back_form_default = {
container: "feed_back_form_container",
backArrow: "feed_back_form_backArrow",
title: "feed_back_form_title",
subtitle: "feed_back_form_subtitle",
content: "feed_back_form_content",
formGrid: "feed_back_form_formGrid",
fullSpan: "feed_back_form_fullSpan",
textLeft: "feed_back_form_textLeft",
errorText: "feed_back_form_errorText",
actions: "feed_back_form_actions",
reaction: "feed_back_form_reaction",
button: "feed_back_form_button",
buttonGray: "feed_back_form_buttonGray",
buttonRed: "feed_back_form_buttonRed",
feedbackStatus: "feed_back_form_feedbackStatus",
emoji: "feed_back_form_emoji"
};
// src/components/form/feed-back-form/index.tsx
import { ArrowLeft2 as ArrowLeft22 } from "iconsax-react";
import { useState as useState3 } from "react";
// src/components/inputs/button/button.module.css
var button_default = {
btn: "button_btn",
custom_default: "button_custom_default",
custom_destructive: "button_custom_destructive",
custom_outline: "button_custom_outline",
custom_secondary: "button_custom_secondary",
custom_ghost: "button_custom_ghost",
custom_link: "button_custom_link",
custom_default_size: "button_custom_default_size",
custom_sm_size: "button_custom_sm_size",
custom_lg_size: "button_custom_lg_size",
custom_icon_size: "button_custom_icon_size"
};
// src/components/inputs/button/index.tsx
import { cva } from "class-variance-authority";
import { forwardRef } from "react";
import { jsx as jsx4 } from "react/jsx-runtime";
var buttonVariants = cva(button_default.btn, {
variants: {
variant: {
default: button_default.custom_default,
destructive: button_default.custom_destructive,
outline: button_default.custom_outline,
secondary: button_default.custom_secondary,
ghost: button_default.custom_ghost,
link: button_default.custom_link
},
size: {
default: button_default.custom_default_size,
sm: button_default.custom_sm_size,
lg: button_default.custom_lg_size,
icon: button_default.custom_icon_size
}
},
defaultVariants: {
variant: "default",
size: "default"
}
});
var Button = forwardRef(
({ variant, size, ...props }, ref) => {
return /* @__PURE__ */ jsx4(
"button",
{
className: buttonVariants({ variant, size }),
ref,
...props
}
);
}
);
Button.displayName = "Button";
// src/components/inputs/input/input.module.css
var input_default = {
input: "input_input",
label: "input_label",
required: "input_required",
error: "input_error"
};
// src/components/inputs/input/index.tsx
import {
forwardRef as forwardRef2
} from "react";
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
var Input2 = forwardRef2(
({ className, type, ...props }, ref) => {
return /* @__PURE__ */ jsx5(
"input",
{
className: `${input_default.input} ${className}`,
type,
ref,
...props
}
);
}
);
Input2.displayName = "Input";
var Label = forwardRef2(
({ className, children, required, ...props }, ref) => {
return (
// biome-ignore lint/a11y/noLabelWithoutControl: Composable
/* @__PURE__ */ jsxs3("label", { ref, ...props, className: `${input_default.label} ${className}`, children: [
children,
required && /* @__PURE__ */ jsx5("span", { className: input_default.required })
] })
);
}
);
Label.displayName = "Label";
var InputError = forwardRef2(
({ showError, message, className, ...props }, ref) => {
return showError ? /* @__PURE__ */ jsx5("span", { ref, ...props, className: `${input_default.error} ${className}`, children: message }) : null;
}
);
InputError.displayName = "Input Error";
// src/components/inputs/select/select.module.css
var select_default = {
select: "select_select"
};
// src/components/inputs/select/index.tsx
import { forwardRef as forwardRef3 } from "react";
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
var Select = forwardRef3(
({ className, onChange, options, placeholder, value, ...props }, ref) => {
return /* @__PURE__ */ jsxs4(
"select",
{
ref,
value,
className: `${select_default.select} ${className}`,
onChange: (e) => onChange?.(e.target.value),
...props,
children: [
placeholder && /* @__PURE__ */ jsx6("option", { value: "", children: placeholder }),
options.map((option) => /* @__PURE__ */ jsx6("option", { value: option.value, children: option.label }, option.value))
]
}
);
}
);
Select.displayName = "Select";
// src/components/inputs/text-editor/text-editor.module.css
var text_editor_default = {
container: "text_editor_container",
label: "text_editor_label",
editor: "text_editor_editor",
toolbarButton: "text_editor_toolbarButton",
hiddenFileInput: "text_editor_hiddenFileInput"
};
// src/components/inputs/text-editor/index.tsx
import Editor, {
BtnBold,
BtnBulletList,
BtnClearFormatting,
BtnItalic,
BtnLink,
BtnNumberedList,
BtnStyles,
BtnUnderline,
Toolbar
} from "react-simple-wysiwyg";
import { useEffect, useRef, useState as useState2 } from "react";
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
function RichTextEditorComponent({
label,
name = "",
onChange,
placeholder = "Start typing...",
value = ""
}) {
const [editorValue, setEditorValue] = useState2(value);
const fileInputRef = useRef(null);
useEffect(() => {
setEditorValue(value);
}, [value]);
const handleEditorChange = (event) => {
const newValue = event.target.value;
setEditorValue(newValue);
onChange?.(newValue);
};
const handleImageSelect = () => {
if (fileInputRef.current) {
fileInputRef.current.click();
}
};
const handleFileChange = (e) => {
const file = e.target.files?.[0];
if (file) {
const reader = new FileReader();
reader.onload = () => {
const imageUrl = reader.result;
const imageHtml = `<img src="${imageUrl}" alt="uploaded-image" style="max-width:100%; height:auto; margin:8px 0;" />`;
const updatedContent = editorValue + imageHtml;
setEditorValue(updatedContent);
onChange?.(updatedContent);
};
reader.readAsDataURL(file);
}
e.target.value = "";
};
return /* @__PURE__ */ jsxs5("div", { className: text_editor_default.container, children: [
label && /* @__PURE__ */ jsx7("p", { children: label }),
/* @__PURE__ */ jsx7(
Editor,
{
value: editorValue,
className: text_editor_default.editor,
name,
onChange: handleEditorChange,
placeholder,
children: /* @__PURE__ */ jsxs5(Toolbar, { children: [
/* @__PURE__ */ jsx7(BtnBold, {}),
/* @__PURE__ */ jsx7(BtnItalic, {}),
/* @__PURE__ */ jsx7(BtnBulletList, {}),
/* @__PURE__ */ jsx7(BtnUnderline, {}),
/* @__PURE__ */ jsx7(BtnLink, {}),
/* @__PURE__ */ jsx7(BtnNumberedList, {}),
/* @__PURE__ */ jsx7(BtnStyles, {}),
/* @__PURE__ */ jsx7(BtnClearFormatting, {}),
/* @__PURE__ */ jsx7(
"button",
{
className: text_editor_default.toolbarButton,
onClick: handleImageSelect,
title: "Insert Image",
children: "\u{1F4F7}"
}
),
/* @__PURE__ */ jsx7(
"input",
{
accept: "image/*",
onChange: handleFileChange,
ref: fileInputRef,
style: { display: "none" },
type: "file"
}
)
] })
}
)
] });
}
// src/libs/extract-user-data.ts
var extractUserData = (authStatus) => {
if (!authStatus || !authStatus.strategy) return { name: "", email: "" };
if (authStatus.strategy === "user-specified") {
return authStatus.userData;
}
let storage;
switch (authStatus.strategy) {
case "sessionStorage":
storage = sessionStorage;
break;
default:
storage = localStorage;
break;
}
try {
if (authStatus.method === "string") {
return {
email: storage.getItem(authStatus.userKeys.email) || "",
name: storage.getItem(authStatus.userKeys.name) || ""
};
}
if (authStatus.method === "object" && authStatus.objectName) {
const userObjectRaw = storage.getItem(authStatus.objectName);
if (!userObjectRaw) return { email: "", name: "" };
const parsed = JSON.parse(userObjectRaw);
return {
email: parsed[authStatus.userKeys.email] || "",
name: parsed[authStatus.userKeys.name] || ""
};
}
} catch (err) {
console.error("Error extracting user data:", err);
}
return { email: "", name: "" };
};
// src/components/form/feed-back-form/index.tsx
import { Group, Text as Text3 } from "@mantine/core";
import { useForm } from "@mantine/form";
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
var FeedBackForm = ({
apiKey,
apiURL,
authStatus,
headers,
onBack,
supportGuide
}) => {
const userData = extractUserData(authStatus);
const [loading, setLoading] = useState3(false);
const [error, setError] = useState3("");
const [success, setSuccess] = useState3("");
const form = useForm({
initialValues: {
email: userData?.email ?? "",
first_name: userData?.name ?? "",
last_name: "",
message: "",
rating: "",
subject: ""
},
validate: {
email: (value) => /^\S+@\S+$/.test(value.trim()) ? null : "Invalid email",
first_name: (value) => !value.trim() ? "First Name is required" : null,
message: (value) => !value.trim() ? "Message is required" : null,
subject: (value) => !value.trim() ? "Subject is required" : null
}
});
const isSelected = (rating) => form.values.rating === rating;
const onRate = (rating) => () => form.setFieldValue("rating", isSelected(rating) ? "" : rating);
const handleSubmit = async (values) => {
setError("");
setSuccess("");
setLoading(true);
try {
const response = await fetch(`${apiURL}`, {
body: JSON.stringify({
email: values.email,
message: values.message,
name: `${values.first_name} ${values.last_name}`.trim(),
subject: values.subject,
system: supportGuide?.system,
topicId: 17
}),
headers: {
"Content-Type": "application/json",
"X-API-Key": `${apiKey}`,
...headers
},
method: "POST"
});
if (response.ok) {
setSuccess("Your issue has been reported successfully!");
form.reset();
setTimeout(() => {
setSuccess("");
}, 3e3);
} else {
throw new Error(`Failed with status code ${response.status}`);
}
} catch (err) {
console.error(err);
setError("Failed to report the issue. Please try again.");
setTimeout(() => {
setError("");
}, 3e3);
} finally {
setLoading(false);
}
};
return /* @__PURE__ */ jsxs6("div", { className: feed_back_form_default.container, children: [
/* @__PURE__ */ jsx8(
ArrowLeft22,
{
color: "#292D32",
size: 35,
className: feed_back_form_default.backArrow,
onClick: onBack
}
),
/* @__PURE__ */ jsx8(Text3, { className: feed_back_form_default.title, fw: "bold", children: "Feedback Form" }),
/* @__PURE__ */ jsxs6(Text3, { className: feed_back_form_default.subtitle, fz: "xs", children: [
userData?.name,
" Kindly fill the feedback form as honestly as possible so we can understand how to serve you better."
] }),
/* @__PURE__ */ jsx8("form", { className: feed_back_form_default.formGrid, onSubmit: form.onSubmit(handleSubmit), children: /* @__PURE__ */ jsxs6("div", { className: feed_back_form_default.content, children: [
!userData?.name && /* @__PURE__ */ jsxs6(Group, { children: [
/* @__PURE__ */ jsx8(Label, { required: true, children: "First Name" }),
/* @__PURE__ */ jsx8(
Input2,
{
type: "text",
placeholder: "Enter first name",
className: feed_back_form_default.subtitle,
...form.getInputProps("first_name")
}
)
] }),
form.errors.first_name && /* @__PURE__ */ jsx8(Text3, { c: "red", fz: "xs", children: form.errors.first_name }),
!userData?.name && /* @__PURE__ */ jsxs6(Group, { children: [
/* @__PURE__ */ jsx8(Label, { required: true, children: "Last Name" }),
/* @__PURE__ */ jsx8(
Input2,
{
type: "text",
placeholder: "Enter last name",
className: feed_back_form_default.subtitle,
...form.getInputProps("last_name")
}
)
] }),
form.errors.last_name && /* @__PURE__ */ jsx8(Text3, { c: "red", fz: "xs", children: form.errors.last_name }),
!userData?.email && /* @__PURE__ */ jsxs6(Group, { children: [
/* @__PURE__ */ jsx8(Label, { required: true, children: "Email Address" }),
/* @__PURE__ */ jsx8(
Input2,
{
type: "email",
placeholder: "Enter email address",
className: feed_back_form_default.subtitle,
...form.getInputProps("email")
}
)
] }),
form.errors.email && /* @__PURE__ */ jsx8(Text3, { c: "red", fz: "xs", children: form.errors.email }),
/* @__PURE__ */ jsxs6(Group, { children: [
/* @__PURE__ */ jsx8(Label, { required: true, children: "Subject" }),
/* @__PURE__ */ jsx8(
Input2,
{
type: "text",
placeholder: "Enter the subject of your feedback",
className: feed_back_form_default.subtitle,
...form.getInputProps("subject")
}
)
] }),
form.errors.subject && /* @__PURE__ */ jsx8(Text3, { c: "red", fz: "xs", children: form.errors.subject }),
/* @__PURE__ */ jsxs6(Group, { children: [
/* @__PURE__ */ jsx8(Label, { required: true, children: "Message" }),
/* @__PURE__ */ jsx8(
RichTextEditorComponent,
{
name: "message",
onChange: (value) => form.setFieldValue("message", value),
placeholder: "Enter your feedback message",
value: form.values.message
}
)
] }),
form.errors.message && /* @__PURE__ */ jsx8(Text3, { c: "red", fz: "xs", children: form.errors.message }),
/* @__PURE__ */ jsxs6("div", { className: feed_back_form_default.reaction, children: [
/* @__PURE__ */ jsx8(
Reaction,
{
selected: isSelected("Very Bad"),
onReact: onRate("Very Bad"),
children: "\u{1F621}"
}
),
/* @__PURE__ */ jsx8(Reaction, { onReact: onRate("Bad"), selected: isSelected("Bad"), children: "\u{1F614}" }),
/* @__PURE__ */ jsx8(
Reaction,
{
onReact: onRate("Neutral"),
selected: isSelected("Neutral"),
children: "\u{1F611}"
}
),
/* @__PURE__ */ jsx8(Reaction, { onReact: onRate("Good"), selected: isSelected("Good"), children: "\u{1F642}" }),
/* @__PURE__ */ jsx8(
Reaction,
{
onReact: onRate("Excellent"),
selected: isSelected("Excellent"),
children: "\u{1F970}"
}
)
] }),
/* @__PURE__ */ jsxs6("div", { className: feed_back_form_default.actions, children: [
/* @__PURE__ */ jsx8(
Button,
{
className: `${feed_back_form_default.button} ${feed_back_form_default.buttonGray}`,
type: "button",
onClick: () => {
form.reset();
setError("");
setSuccess("");
},
children: "Cancel"
}
),
/* @__PURE__ */ jsx8(
Button,
{
className: `${feed_back_form_default.button} ${feed_back_form_default.buttonRed}`,
type: "submit",
disabled: loading,
children: loading ? "Sending..." : "Send"
}
)
] }),
/* @__PURE__ */ jsxs6("div", { className: feed_back_form_default.feedbackStatus, children: [
error && /* @__PURE__ */ jsx8(Text3, { c: "red", py: 8, children: error }),
success && /* @__PURE__ */ jsx8(Text3, { c: "green", py: 8, children: success })
] })
] }) })
] });
};
function Reaction({ children, onReact, selected }) {
return /* @__PURE__ */ jsx8(
"button",
{
type: "button",
onClick: onReact,
"aria-selected": selected,
className: feed_back_form_default.emoji,
children
}
);
}
// src/components/form/report-an-issue/report-an-issue.module.css
var report_an_issue_default = {
container: "report_an_issue_container",
title: "report_an_issue_title",
subtitle: "report_an_issue_subtitle",
content: "report_an_issue_content",
formGrid: "report_an_issue_formGrid",
textLeft: "report_an_issue_textLeft",
errorText: "report_an_issue_errorText",
actions: "report_an_issue_actions",
button: "report_an_issue_button",
buttonGray: "report_an_issue_buttonGray",
buttonRed: "report_an_issue_buttonRed",
feedbackStatus: "report_an_issue_feedbackStatus"
};
// src/components/form/report-an-issue/index.tsx
import { Group as Group2, Text as Text4 } from "@mantine/core";
import { useForm as useForm2 } from "@mantine/form";
import { useEffect as useEffect2, useState as useState4 } from "react";
// src/libs/issue-types.ts
var ISSUE_TYPES = Object.freeze([
{ label: "Payment & Account Issues", value: "16" },
{ label: "IT Support", value: "14" },
{ label: "Feedback", value: "17" },
{ label: "AFTL NG", value: "18" },
{ label: "Trade", value: "19" },
{ label: "Exchange", value: "20" },
{ label: "Banking", value: "21" },
{ label: "Data", value: "22" },
{ label: "General", value: "15" }
]);
// src/components/form/report-an-issue/index.tsx
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
var ReportAnIssueForm = ({
apiKey,
apiURL,
authStatus,
issueType
}) => {
const userData = extractUserData(authStatus);
const [loading, setLoading] = useState4(false);
const [error, setError] = useState4("");
const [success, setSuccess] = useState4("");
const DEFAULT_TYPE_LABELS = [
"Payment & Account Issues",
"IT Support",
"Feedback",
"General"
];
const issueTypes = ISSUE_TYPES.filter((type) => {
return DEFAULT_TYPE_LABELS.includes(type.label) || type.label === issueType;
});
useEffect2(() => {
if (issueType && !ISSUE_TYPES.some((type) => type.label === issueType)) {
console.warn(
`[ReportAnIssueForm] Invalid additionalIssueType "${issueType}" passed. Check ISSUE_TYPES for valid labels.`
);
}
}, [issueType]);
const form = useForm2({
initialValues: {
email: userData?.email ?? "",
message: "",
name: userData?.name ?? "",
subject: "",
topicId: ""
},
validate: {
email: (value) => /^\S+@\S+$/.test(value.trim()) ? null : "Invalid email",
message: (value) => !value.trim() ? "Message is required" : null,
name: (value) => !value.trim() ? "Name is required" : null,
subject: (value) => !value.trim() ? "Subject is required" : null,
topicId: (value) => !value ? "Please select an issue type" : null
}
});
const handleSubmit = async (values) => {
setError("");
setSuccess("");
setLoading(true);
try {
const response = await fetch(`${apiURL}`, {
body: JSON.stringify({
...values
}),
headers: {
"Content-Type": "application/json",
"X-API-Key": `${apiKey}`
},
method: "POST"
});
if (response.ok) {
setSuccess("Your issue has been reported successfully!");
form.reset();
setTimeout(() => {
setSuccess("");
}, 3e3);
} else {
throw new Error(`Failed with status code ${response.status}`);
}
} catch (err) {
console.error(err);
setError("Failed to report the issue. Please try again.");
setTimeout(() => {
setError("");
}, 3e3);
} finally {
setLoading(false);
}
};
return /* @__PURE__ */ jsxs7("div", { className: report_an_issue_default.container, children: [
/* @__PURE__ */ jsx9(Text4, { fw: "bold", children: "Report an Issue" }),
/* @__PURE__ */ jsxs7(Text4, { fz: "xs", children: [
userData?.name,
" Kindly fill the form as correctly as possible so we can understand how to help you."
] }),
/* @__PURE__ */ jsx9(
"form",
{
className: report_an_issue_default.formGrid,
onSubmit: form.onSubmit(handleSubmit),
autoComplete: "off",
children: /* @__PURE__ */ jsxs7("div", { className: report_an_issue_default.content, children: [
!userData.name && /* @__PURE__ */ jsxs7(Group2, { className: "flex-1", children: [
/* @__PURE__ */ jsx9(Label, { htmlFor: "name", required: true, children: "Name" }),
/* @__PURE__ */ jsx9(
Input2,
{
className: report_an_issue_default.subtitle,
...form.getInputProps("name"),
placeholder: "Enter your full name"
}
),
form.errors.name && /* @__PURE__ */ jsx9(Text4, { c: "red", fz: "xs", children: form.errors.name })
] }),
!userData.email && /* @__PURE__ */ jsxs7(Group2, { className: "flex-1", children: [
/* @__PURE__ */ jsx9(Label, { htmlFor: "email", required: true, children: "Email Address" }),
/* @__PURE__ */ jsx9(
Input2,
{
className: report_an_issue_default.subtitle,
...form.getInputProps("email"),
placeholder: "Enter your email address"
}
),
form.errors.email && /* @__PURE__ */ jsx9(Text4, { c: "red", fz: "xs", children: form.errors.email })
] }),
/* @__PURE__ */ jsxs7(Group2, { children: [
/* @__PURE__ */ jsx9(Label, { htmlFor: "subject", required: true, children: "Subject" }),
/* @__PURE__ */ jsx9(
Input2,
{
className: report_an_issue_default.subtitle,
...form.getInputProps("subject"),
placeholder: "Enter the subject of your issue"
}
),
form.errors.subject && /* @__PURE__ */ jsx9(Text4, { c: "red", fz: "xs", children: form.errors.subject })
] }),
/* @__PURE__ */ jsxs7(Group2, { children: [
/* @__PURE__ */ jsx9(Label, { htmlFor: "topicId", required: true, children: "Issue Type" }),
/* @__PURE__ */ jsx9(
Select,
{
id: "topicId",
name: "topicId",
onChange: (value) => form.setFieldValue("topicId", value),
options: issueTypes || [],
placeholder: "Select an issue type",
value: form.values.topicId
}
),
form.errors.topicId && /* @__PURE__ */ jsx9(Text4, { c: "red", fz: "xs", children: form.errors.topicId })
] }),
/* @__PURE__ */ jsxs7(Group2, { children: [
/* @__PURE__ */ jsx9(Label, { htmlFor: "message", required: true, children: "Message" }),
/* @__PURE__ */ jsx9(
RichTextEditorComponent,
{
name: "message",
onChange: (value) => form.setFieldValue("message", value),
placeholder: "Enter your message",
value: form.values.message
}
),
form.errors.message && /* @__PURE__ */ jsx9(Text4, { c: "red", fz: "xs", children: form.errors.message })
] }),
/* @__PURE__ */ jsxs7("div", { className: report_an_issue_default.actions, children: [
/* @__PURE__ */ jsx9(
Button,
{
className: `${report_an_issue_default.button} ${report_an_issue_default.buttonGray}`,
type: "button",
onClick: () => {
form.reset();
setError("");
setSuccess("");
},
children: "Cancel"
}
),
/* @__PURE__ */ jsx9(
Button,
{
className: `${report_an_issue_default.button} ${report_an_issue_default.buttonRed}`,
type: "submit",
disabled: loading,
children: loading ? "Sending..." : "Send"
}
)
] })
] })
}
),
/* @__PURE__ */ jsxs7("div", { className: report_an_issue_default.feedbackStatus, children: [
error && /* @__PURE__ */ jsx9(Text4, { mb: 14, c: "red", children: error }),
success && /* @__PURE__ */ jsx9(Text4, { mb: 14, c: "green", children: success })
] })
] });
};
// src/components/live-chat/index.tsx
import Picker from "emoji-picker-react";
// src/components/live-chat/live-chat.module.css
var live_chat_default = {
wrapper: "live_chat_wrapper",
input: "live_chat_input",
container: "live_chat_container"
};
// src/components/live-chat/index.tsx
import { ActionIcon, Center, Input as Input3, Stack as Stack2, Text as Text5 } from "@mantine/core";
import { useForm as useForm3 } from "@mantine/form";
import { Messages, Send2 } from "iconsax-react";
import { useState as useState5 } from "react";
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
function LiveChat() {
const form = useForm3({
initialValues: {
message: ""
}
});
const [messages, setMessages] = useState5([]);
const [showEmojiPicker, setShowEmojiPicker] = useState5(false);
const header = /* @__PURE__ */ jsxs8(Stack2, { align: "center", children: [
/* @__PURE__ */ jsx10(Text5, { fw: 600, fz: 18, inherit: true, children: "Live Chat" }),
/* @__PURE__ */ jsx10(Text5, { fz: 14, inherit: true, opacity: 0.6, children: "Messages from the team will be shown here." })
] });
const emptyContent = /* @__PURE__ */ jsx10(Center, { h: "100%", children: /* @__PURE__ */ jsxs8(Stack2, { align: "center", c: "#686161", maw: 288, children: [
/* @__PURE__ */ jsx10(Messages, { color: "#686161", size: 40, variant: "Outline" }),
/* @__PURE__ */ jsx10(Text5, { fw: "bold", fz: 14, ta: "center", children: "Messages from the team will be shown here" })
] }) });
const handleEmojiSelect = (emojiData) => {
const message = form.values.message;
form.setFieldValue("message", message + emojiData.emoji);
setShowEmojiPicker(false);
};
const handleSendMessage = () => {
if (form.values.message.trim()) {
setMessages((prevMessages) => [...prevMessages, form.values.message]);
form.setFieldValue("message", "");
}
};
const messageInput = /* @__PURE__ */ jsxs8(Stack2, { mt: 20, children: [
/* @__PURE__ */ jsx10(
Input3,
{
classNames: {
wrapper: live_chat_default.wrapper,
input: live_chat_default.input
},
onChange: (event) => form.setFieldValue("message", event.currentTarget.value),
placeholder: "Type a Message",
rightSection: /* @__PURE__ */ jsx10(
ActionIcon,
{
bg: "#e2261c",
color: "#e2261c",
onClick: handleSendMessage,
radius: 4,
size: 35,
variant: "filled",
children: /* @__PURE__ */ jsx10(Send2, { color: "#FFFFFF", size: 20, variant: "Bold" })
}
),
value: form.values.message
}
),
showEmojiPicker && /* @__PURE__ */ jsx10("div", { style: { marginTop: "8px" }, children: /* @__PURE__ */ jsx10(Picker, { onEmojiClick: handleEmojiSelect }) })
] });
return /* @__PURE__ */ jsxs8("div", { className: live_chat_default.container, children: [
header,
/* @__PURE__ */ jsxs8(
Stack2,
{
p: "md",
style: {
display: "flex",
flexDirection: "column",
flexGrow: 1,
justifyContent: "space-between",
width: "100%"
},
children: [
/* @__PURE__ */ jsxs8(Stack2, { style: { overflowY: "auto", flexGrow: 1, width: "100%" }, children: [
/* @__PURE__ */ jsx10("div", { children: emptyContent }),
messages.map((msg) => /* @__PURE__ */ jsx10(Text5, { mb: "xs", children: msg }, msg))
] }),
messageInput
]
}
)
] });
}
// src/components/navigation/navigation.module.css
var navigation_default = {
container: "navigation_container",
tabsRoot: "navigation_tabsRoot",
tab: "navigation_tab",
tabLabel: "navigation_tabLabel",
tabsList: "navigation_tabsList"
};
// src/components/navigation/index.tsx
import { Tabs } from "@mantine/core";
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
var Navigation = ({
navigate,
sections = defaultConfiguration.sections
}) => {
return /* @__PURE__ */ jsx11("nav", { className: navigation_default.container, children: /* @__PURE__ */ jsx11(
Tabs,
{
variant: "none",
defaultValue: "home",
radius: "xl",
styles: {
root: {
display: "flex",
flexDirection: "column",
justifyContent: "space-between"
},
tab: {
textAlign: "center",
backgroundColor: "transparent",
border: "none",
justifyContent: "center",
alignItems: "center"
},
tabLabel: {
alignItems: "center",
display: "flex",
flexDirection: "column",
justifyContent: "center",
textAlign: "center",
gap: "5px"
}
},
classNames: {
tab: navigation_default.tab,
list: navigation_default.tabList
},
children: /* @__PURE__ */ jsx11(Tabs.List, { children: sections?.map((section) => /* @__PURE__ */ jsx11(
Tabs.Tab,
{
value: section.id,
onClick: () => navigate(section.id),
hidden: !(section.show ?? true),
children: /* @__PURE__ */ jsxs9("div", { children: [
section.icon,
section.title
] })
},
section.id
)) })
}
) });
};
// src/components/faqs/info/wrapper.tsx
import { jsx as jsx12 } from "react/jsx-runtime";
var SupportInfoWrapper = ({ id, onBack, supportGuide }) => {
const item = supportGuide?.titles?.find((t) => t.id === id);
if (!item) {
return /* @__PURE__ */ jsx12("div", { children: "Support info not found." });
}
return /* @__PURE__ */ jsx12(SupportInfo, { lists: item.guideSections || [], onBack, title: item.heading });
};
// src/components/bot/index.tsx
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
var FeedBackBot = (defaultProps) => {
if (!defaultProps.apiKey || !defaultProps.apiURL) {
throw new Error("API URL and API key not defined");
}
const props = deepMerge(defaultConfiguration, defaultProps);
console.log("Feedback Bot Props:", props);
const { authStatus, sections, supportGuide } = props;
const [dialogOpened, setDialogOpened] = useState6(false);
const [currentView, setCurrentView] = useState6(
(props?.sections ?? [])[0].id
);
const [selectedId, setSelectedId] = useState6(null);
const toggleDialog = () => setDialogOpened((prev) => !prev);
const ref = useClickOutside(() => setDialogOpened(false));
const goToView = (view, id) => {
setSelectedId(id ?? null);
setCurrentView(view);
};
const viewMap = {
[View.Chat]: /* @__PURE__ */ jsx13(LiveChat, {}),
[View.Feedback]: /* @__PURE__ */ jsx13(
FeedBackForm,
{
apiKey: props.apiKey,
apiURL: props.apiURL,
authStatus,
onBack: () => setCurrentView(View.Home),
supportGuide
}
),
[View.Home]: /* @__PURE__ */ jsx13(
Support,
{
apiKey: props.apiKey,
apiURL: props.apiURL,
navigate: (view, id) => {
if (view === "support-info" && id !== void 0) {
goToView(View.Info, id);
} else if (view === "feed-back-form") {
goToView(View.Feedback);
}
},
supportGuide
}
),
[View.Info]: /* @__PURE__ */ jsx13(
SupportInfoWrapper,
{
id: selectedId,
onBack: () => setCurrentView(View.Home),
supportGuide
}
),
[View.Issue]: /* @__PURE__ */ jsx13(
ReportAnIssueForm,
{
apiKey: props.apiKey,
apiURL: props.apiURL,
authStatus,
issueType: supportGuide?.system
}
)
};
return /* @__PURE__ */ jsxs10(MantineProvider, { children: [
/* @__PURE__ */ jsx13(
Dialog,
{
mb: 40,
onClose: toggleDialog,
opened: dialogOpened,
p: 0,
radius: "md",
style: { maxWidth: 400, width: "100%" },
withCloseButton: true,
ref,
classNames: { closeButton: "bg-white rounded-lg mt-2" },
children: /* @__PURE__ */ jsxs10(
"div",
{
className: bot_default.dialogContainer,
style: {
background: `linear-gradient(to bottom, ${supportGuide?.gradient?.[0]}, transparent 200px)`
},
children: [
/* @__PURE__ */ jsx13("div", { className: bot_default.dialogContent, children: viewMap[currentView] }),
/* @__PURE__ */ jsx13(Navigation, { sections, navigate: goToView })
]
}
)
}
),
/* @__PURE__ */ jsx13(
ActionIcon2,
{
onClick: toggleDialog,
radius: 4,
size: 40,
style: {
backgroundColor: "#e2261c",
bottom: "20px",
position: "fixed",
right: "20px",
zIndex: 1e3
},
variant: "filled",
children: /* @__PURE__ */ jsxs10(Stack3, { gap: 0, mx: "auto", children: [
/* @__PURE__ */ jsx13(Box, { w: "fit-content", mx: "auto", children: props.icon }),
typeof props.label === "string" ? /* @__PURE__ */ jsx13(Text6, { fz: 8, fw: 700, ta: "center", children: props.label }) : props.label
] })
}
)
] });
};
export {
FeedBackBot,
defaultPosition,
defaultSections,
defaultSupportGuide
};
//# sourceMappingURL=index.js.map