186 lines
5.1 KiB
JavaScript
186 lines
5.1 KiB
JavaScript
(() => {
|
|
const introMessage =
|
|
"Witaj, jestem twoim wirtualnym agentem Krzak.org, w czym mogę Ci pomóc?";
|
|
const baseReplies = [
|
|
"Niestety, nie umiem jeszcze tego zrobić",
|
|
"Nie jestem pewien o co Ci chodzi",
|
|
];
|
|
const offerFrom = [
|
|
"pedałów",
|
|
"pajaca",
|
|
"noży",
|
|
"gwoździ",
|
|
"przypraw",
|
|
"słoika",
|
|
"słoików",
|
|
"tabletek",
|
|
"spreju",
|
|
"narzędzi",
|
|
"samolotu",
|
|
"ostrzałki",
|
|
"szafki",
|
|
"pojemnika",
|
|
"pojemników",
|
|
"ładowarki",
|
|
"ładowarek",
|
|
"wieszaków",
|
|
"wieszaka",
|
|
"półki",
|
|
"półek",
|
|
"ryby",
|
|
];
|
|
const offerTo = [
|
|
"gwoździ",
|
|
"roweru",
|
|
"krojenia cebuli",
|
|
"pedałów",
|
|
"latania",
|
|
"łatania",
|
|
"podatków",
|
|
"sprzątania",
|
|
"wyrywania zębów",
|
|
"zmywarki",
|
|
"śmieci",
|
|
"krojenia chleba",
|
|
"krojenia ogórków",
|
|
"krojenia pomidorów",
|
|
"krojenia cebuli",
|
|
"krojenia ogórków",
|
|
"krojenia pomidorów",
|
|
"jedzenia",
|
|
"picia",
|
|
"kuchni",
|
|
"książek",
|
|
"ryb",
|
|
];
|
|
|
|
const chatRoot = document.createElement("div");
|
|
chatRoot.className = "ai-chat";
|
|
chatRoot.innerHTML = `
|
|
<button class="ai-chat__fab" type="button" aria-expanded="false" aria-controls="ai-chat-panel">AI chat</button>
|
|
<section class="ai-chat__panel" id="ai-chat-panel" aria-hidden="true">
|
|
<header class="ai-chat__header">
|
|
<strong>Agent Krzak.org</strong>
|
|
<button class="ai-chat__close" type="button" aria-label="Close chat">x</button>
|
|
</header>
|
|
<div class="ai-chat__messages"></div>
|
|
<form class="ai-chat__form">
|
|
<input class="ai-chat__input" type="text" placeholder="Napisz wiadomość..." autocomplete="off" />
|
|
<button class="ai-chat__send" type="submit">Wyslij</button>
|
|
</form>
|
|
</section>
|
|
`;
|
|
document.body.appendChild(chatRoot);
|
|
|
|
const fab = chatRoot.querySelector(".ai-chat__fab");
|
|
const panel = chatRoot.querySelector(".ai-chat__panel");
|
|
const closeBtn = chatRoot.querySelector(".ai-chat__close");
|
|
const messages = chatRoot.querySelector(".ai-chat__messages");
|
|
const form = chatRoot.querySelector(".ai-chat__form");
|
|
const input = chatRoot.querySelector(".ai-chat__input");
|
|
const sendBtn = chatRoot.querySelector(".ai-chat__send");
|
|
const backToTop = document.getElementById("back-to-top");
|
|
const viewport = window.visualViewport;
|
|
|
|
function addMessage(text, fromUser) {
|
|
const bubble = document.createElement("p");
|
|
bubble.className = fromUser
|
|
? "ai-chat__bubble ai-chat__bubble--user"
|
|
: "ai-chat__bubble";
|
|
bubble.textContent = text;
|
|
messages.appendChild(bubble);
|
|
messages.scrollTop = messages.scrollHeight;
|
|
}
|
|
|
|
function openChat() {
|
|
panel.classList.add("is-open");
|
|
panel.setAttribute("aria-hidden", "false");
|
|
fab.setAttribute("aria-expanded", "true");
|
|
if (!messages.hasChildNodes()) {
|
|
addMessage(introMessage, false);
|
|
}
|
|
input.focus();
|
|
syncKeyboardOffset();
|
|
}
|
|
|
|
function closeChat() {
|
|
panel.classList.remove("is-open");
|
|
panel.setAttribute("aria-hidden", "true");
|
|
fab.setAttribute("aria-expanded", "false");
|
|
syncKeyboardOffset();
|
|
}
|
|
|
|
function randomItem(items) {
|
|
return items[Math.floor(Math.random() * items.length)];
|
|
}
|
|
|
|
function buildReply() {
|
|
return `${randomItem(baseReplies)}, ale mogę Ci zaoferować kupno ${randomItem(offerFrom)} do ${randomItem(offerTo)}.`;
|
|
}
|
|
|
|
function syncChatPosition() {
|
|
if (!backToTop) {
|
|
chatRoot.classList.remove("ai-chat--raised");
|
|
return;
|
|
}
|
|
chatRoot.classList.toggle(
|
|
"ai-chat--raised",
|
|
backToTop.classList.contains("visible"),
|
|
);
|
|
}
|
|
|
|
function syncKeyboardOffset() {
|
|
if (!viewport) {
|
|
chatRoot.style.setProperty("--ai-chat-keyboard-offset", "0px");
|
|
return;
|
|
}
|
|
const offset = Math.max(
|
|
0,
|
|
Math.round(window.innerHeight - viewport.height - viewport.offsetTop),
|
|
);
|
|
chatRoot.style.setProperty("--ai-chat-keyboard-offset", `${offset}px`);
|
|
}
|
|
|
|
fab.addEventListener("click", () => {
|
|
if (panel.classList.contains("is-open")) {
|
|
closeChat();
|
|
return;
|
|
}
|
|
openChat();
|
|
});
|
|
|
|
closeBtn.addEventListener("click", closeChat);
|
|
sendBtn.addEventListener("pointerdown", (event) => {
|
|
// Keep focus on the input so mobile keyboards stay open after sending.
|
|
event.preventDefault();
|
|
});
|
|
|
|
form.addEventListener("submit", (event) => {
|
|
event.preventDefault();
|
|
const text = input.value.trim();
|
|
if (!text) {
|
|
return;
|
|
}
|
|
addMessage(text, true);
|
|
addMessage(buildReply(), false);
|
|
input.value = "";
|
|
input.focus({ preventScroll: true });
|
|
});
|
|
|
|
if (backToTop) {
|
|
const observer = new MutationObserver(syncChatPosition);
|
|
observer.observe(backToTop, {
|
|
attributes: true,
|
|
attributeFilter: ["class"],
|
|
});
|
|
window.addEventListener("resize", syncChatPosition);
|
|
}
|
|
if (viewport) {
|
|
viewport.addEventListener("resize", syncKeyboardOffset);
|
|
viewport.addEventListener("scroll", syncKeyboardOffset);
|
|
}
|
|
window.addEventListener("resize", syncKeyboardOffset);
|
|
syncChatPosition();
|
|
syncKeyboardOffset();
|
|
})();
|