improve chat ui
All checks were successful
Build Container / Build Container (push) Successful in 1m29s
All checks were successful
Build Container / Build Container (push) Successful in 1m29s
This commit is contained in:
parent
2ef2b04e49
commit
81923c4f8c
7 changed files with 170 additions and 48 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import {createIcons, Send, Stars} from "lucide"
|
||||
import {Bot, createIcons, UserRound, Send, Stars} from "lucide"
|
||||
import {useTranslations} from "../i18n/utils.ts"
|
||||
import removeDiacritics from "./removeDiacritics.ts"
|
||||
|
||||
export type ResponseDictType = {
|
||||
|
|
@ -16,6 +17,8 @@ const doors = window.doors
|
|||
const auth = window.auth
|
||||
const doorAction = window.doorAction
|
||||
|
||||
const t = useTranslations(lang)
|
||||
|
||||
const responses =
|
||||
lang === "de"
|
||||
? (await import("./chatDict_de")).default
|
||||
|
|
@ -25,19 +28,51 @@ const responses =
|
|||
const sortedResponses = responses.sort(
|
||||
(a, b) => b.priority - a.priority)
|
||||
|
||||
const chatAvatar = `
|
||||
<div class="chat-image avatar">
|
||||
<div class="w-10 rounded-full ${lang === 'uwu' ? 'bg-transparent' : 'bg-primary'} flex items-center justify-center">
|
||||
${lang === 'uwu' ? '<span class="text-4xl">🥺</span>' : '<i data-lucide="bot"></i>'}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
|
||||
const chatHeader = `
|
||||
<div class="chat-header">
|
||||
${t("chat.dooris")}
|
||||
</div>
|
||||
`
|
||||
|
||||
const chatAvatarUser = `
|
||||
<div class="chat-image avatar">
|
||||
<div class="w-10 rounded-full ${lang === 'uwu' ? 'bg-transparent' : 'bg-secondary'} flex items-center justify-center">
|
||||
${lang === 'uwu' ? '<span class="text-4xl">🥺</span>' : '<i data-lucide="user-round"></i>'}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
|
||||
const chatHeaderUser = `
|
||||
<div class="chat-header">
|
||||
${t("chat.user")}
|
||||
</div>
|
||||
`
|
||||
|
||||
const chatWait = `
|
||||
<div class="chat chat-start w-full prose" data-waiting>
|
||||
${chatAvatar}
|
||||
${chatHeader}
|
||||
<div class="chat-bubble chat-bubble-primary whitespace-normal min-h-10">
|
||||
<span class="loading loading-dots loading-md"></span>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
|
||||
const templateInjectChat = `
|
||||
<details class="dropdown dropdown-top dropdown-end absolute right-4 bottom-4" id="chat-root">
|
||||
<summary class="btn btn-lg btn-circle btn-primary">
|
||||
<details class="dropdown dropdown-top dropdown-end absolute right-2 bottom-2" id="chat-root">
|
||||
<summary class="btn btn-lg btn-circle btn-primary me-2 mb-2">
|
||||
<i data-lucide="stars"></i>
|
||||
</summary>
|
||||
<div class="dropdown-content card min-h-120 max-h-200 w-80 bg-base-300 p-4 mb-4">
|
||||
<div class="w-full overflow-auto h-full prose leading-5" id="chat"></div>
|
||||
<div class="chat chat-start w-full hidden" id="chat-waiting">
|
||||
<div class="chat-bubble chat-bubble-primary whitespace-normal">
|
||||
<span class="loading loading-dots loading-md"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4"></div>
|
||||
<div class="dropdown-content card h-140 w-90 bg-base-300 p-4 mb-4" style="max-height: min(calc(100vh - 10rem), 50rem); max-width: calc(100vw - 1rem)">
|
||||
<div class="w-full overflow-y-auto h-full prose leading-5 grow pb-4" id="chat"></div>
|
||||
<div class="join mt-auto w-full">
|
||||
<div class="w-full">
|
||||
<label class="input join-item">
|
||||
|
|
@ -79,11 +114,14 @@ function refreshChat() {
|
|||
const chatContainer = document.createElement("div")
|
||||
const chatBubble = document.createElement("div")
|
||||
|
||||
chatBubble.classList.add("chat-bubble", "chat-bubble-primary", "whitespace-normal")
|
||||
chatBubble.classList.add("chat-bubble", "chat-bubble-primary", "whitespace-normal", "min-h-10", "break-[break-word]")
|
||||
chatBubble.style.wordBreak = "break-word"
|
||||
chatBubble.classList.toggle("shimmer", special)
|
||||
chatBubble.id = id
|
||||
chatBubble.dataset.content = message
|
||||
chatContainer.classList.add("chat", "chat-start", "w-full")
|
||||
chatContainer.classList.add("chat", "chat-start", "w-full", "overflow-visible", "hidden", "pe-10")
|
||||
chatContainer.id = id
|
||||
chatContainer.insertAdjacentHTML("afterbegin", chatAvatar)
|
||||
chatContainer.insertAdjacentHTML("afterbegin", chatHeader)
|
||||
chatContainer.append(chatBubble)
|
||||
|
||||
return chatContainer
|
||||
|
|
@ -91,10 +129,16 @@ function refreshChat() {
|
|||
|
||||
|
||||
const templateUser = (message: string) => `
|
||||
<div class="chat chat-end w-full">
|
||||
<div class="chat-bubble chat-bubble-secondary whitespace-normal">${message}</div>
|
||||
<div class="chat chat-end w-full ps-10">
|
||||
${chatAvatarUser}
|
||||
${chatHeaderUser}
|
||||
<div class="chat-bubble chat-bubble-secondary whitespace-normal" style="word-break: break-word;">${message}</div>
|
||||
</div>`
|
||||
|
||||
const chatBubbleIds: Array<string> = []
|
||||
|
||||
console.log(chat)
|
||||
|
||||
chat.forEach(chatItem => {
|
||||
switch (chatItem.type) {
|
||||
case "bot":
|
||||
|
|
@ -102,8 +146,7 @@ function refreshChat() {
|
|||
chatItem.id = `chat-${chatId}`
|
||||
chatId++
|
||||
chatElement?.appendChild(templateBot(chatItem.id, chatItem.message, chatItem.special ?? false))
|
||||
typeBubble(chatItem.id, () => {
|
||||
})
|
||||
chatBubbleIds.push(chatItem.id)
|
||||
}
|
||||
break
|
||||
case "user":
|
||||
|
|
@ -115,16 +158,35 @@ function refreshChat() {
|
|||
break
|
||||
}
|
||||
})
|
||||
chatWaitElement.classList.toggle("hidden", !chatWaiting.value)
|
||||
|
||||
typeBubble(chatBubbleIds)
|
||||
|
||||
chatElement.querySelector("[data-waiting]")?.remove()
|
||||
|
||||
if (chatWaiting.value) {
|
||||
chatElement.insertAdjacentHTML("beforeend", chatWait)
|
||||
}
|
||||
|
||||
chatElement.scrollTo({
|
||||
top: chatElement.scrollHeight,
|
||||
})
|
||||
|
||||
refreshIcons()
|
||||
}
|
||||
|
||||
function typeBubble(id: string, callback: Function) {
|
||||
const element = document.getElementById(id)!
|
||||
function typeBubble(ids: Array<string>) {
|
||||
if (!ids.length) return
|
||||
|
||||
console.log(ids)
|
||||
|
||||
const firstId = ids.slice(0, 1)[0]
|
||||
const restIds = ids.slice(1)!
|
||||
|
||||
const chatContainer = document.getElementById(firstId)!
|
||||
chatContainer.classList.remove('hidden')
|
||||
const chatBubble: HTMLDivElement = chatContainer.querySelector('.chat-bubble')!
|
||||
const tmpDiv = document.createElement("div")
|
||||
tmpDiv.innerHTML = element.getAttribute("data-content") || ""
|
||||
tmpDiv.innerHTML = chatBubble.getAttribute("data-content") || ""
|
||||
|
||||
const typingArray: Array<string> = []
|
||||
|
||||
|
|
@ -144,14 +206,14 @@ function typeBubble(id: string, callback: Function) {
|
|||
function typeChar() {
|
||||
if (charIndex < typingArray.length) {
|
||||
text += typingArray.at(charIndex)
|
||||
element.innerHTML = text
|
||||
chatBubble.innerHTML = text
|
||||
charIndex++
|
||||
setTimeout(typeChar, typingSpeed)
|
||||
chatElement.scrollTo({
|
||||
top: chatElement.scrollHeight,
|
||||
})
|
||||
} else if (callback) {
|
||||
callback()
|
||||
} else if (restIds.length > 0) {
|
||||
typeBubble(restIds)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -320,7 +382,7 @@ function getResponse(message: string) {
|
|||
return {
|
||||
type: "bot" as ChatMessage["type"],
|
||||
message: response.message,
|
||||
special: response.special
|
||||
special: response.special,
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -335,7 +397,6 @@ function getResponse(message: string) {
|
|||
|
||||
document.querySelector("body")?.insertAdjacentHTML("beforeend", templateInjectChat)
|
||||
const chatElement: HTMLDivElement = document.querySelector("#chat")!
|
||||
const chatWaitElement: HTMLDivElement = document.querySelector("#chat-waiting")!
|
||||
|
||||
function initChat() {
|
||||
chat.push({
|
||||
|
|
@ -347,14 +408,20 @@ function initChat() {
|
|||
|
||||
let firstOpen = true
|
||||
|
||||
createIcons({
|
||||
nameAttr: "data-lucide",
|
||||
root: document.querySelector("#chat-root")!,
|
||||
icons: {
|
||||
Stars,
|
||||
Send,
|
||||
},
|
||||
})
|
||||
function refreshIcons() {
|
||||
createIcons({
|
||||
nameAttr: "data-lucide",
|
||||
root: document.querySelector("#chat-root")!,
|
||||
icons: {
|
||||
Stars,
|
||||
Send,
|
||||
UserRound,
|
||||
Bot,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
refreshIcons()
|
||||
|
||||
document.querySelector("#send-chat")!.addEventListener("click", sendMessage)
|
||||
document.querySelector("#chat-text")!.addEventListener("keydown", (e: Event) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue