10 lines
16 KiB
JavaScript
Executable File
10 lines
16 KiB
JavaScript
Executable File
class Chat{constructor({sidebarSelector:e="#chat-sidebar",sidebarContactAttribute:s="data-chat-id",sidebarContactSelector:t=`[${s}]`,searchSelector:a="[data-chat-search]",contentSelector:r="[data-chat]",inputSelector:i="[data-chat-input]",sendSelector:m="[data-send]",errorSelector:o="[data-error]",usernameSelector:n="[data-chat-username]",data:u=[]}={}){this.sidebar=document.querySelector(e),this.sidebarContactAttribute=s,this.sidebarContactSelector=t,this.searchInput=document.querySelector(a),this.chatContent=document.querySelector(r),this.chatInput=document.querySelector(i),this.sendButton=document.querySelector(m),this.errorElement=document.querySelector(o),this.usernameElement=document.querySelector(n),this.activeChatId=null,this.chatData=Array.isArray(u)?u:[],this.init()}init(){var e,s=this.chatData[0];this.setupSearch(),this.sidebar&&(this.sidebar.addEventListener("click",e=>{e=e.target.closest(this.sidebarContactSelector);e&&this.switchChat(e.dataset.chatId,e)}),s)&&(e=this.sidebar.querySelector(`[${this.sidebarContactAttribute}="${s.id}"]`),this.switchChat(s.id,e)),this.sendButton&&this.sendButton.addEventListener("click",()=>this.sendMessage()),this.chatInput&&(this.chatInput.addEventListener("keypress",e=>{"Enter"===e.key&&(e.preventDefault(),this.sendMessage())}),this.chatInput.addEventListener("input",()=>{var e=this.chatInput.value.trim();this.sendButton.disabled=!e,this.errorElement&&e&&(this.errorElement.classList.remove("d-block"),this.errorElement.classList.add("d-none"),this.errorTimeout)&&clearTimeout(this.errorTimeout)}))}getChatById(s){return this.chatData.find(e=>e.id===s)}switchChat(e,s=null){var t=this.getChatById(e);t&&(this.activeChatId=e,this.renderMessages(t.messages),this.sidebar&&this.sidebar.querySelectorAll(this.sidebarContactSelector).forEach(e=>e.classList.remove("active")),s&&s.classList.add("active"),this.chatInput?.focus(),this.usernameElement&&(this.usernameElement.innerHTML=t.contact.name),setTimeout(()=>{var e=window.SimpleBar?.instances?.get(this.chatContent),e=e?e.getScrollElement():this.chatContent;e.scrollTop=e.scrollHeight},50))}renderMessages(e){var s;e&&this.chatContent&&(((s=window.SimpleBar?.instances?.get(this.chatContent))?s.getContentElement():this.chatContent).innerHTML=e.map(e=>{var s="me"===e.from;return`
|
||
<div class="d-flex align-items-start gap-2 my-3 chat-item ${s?"text-end justify-content-end":""}">
|
||
${s?"":`<img src="${e.avatar}" class="avatar-md rounded-circle" alt="User">`}
|
||
<div>
|
||
<div class="chat-message py-2 px-3 ${s?"bg-info-subtle":"bg-warning-subtle"} rounded">${e.text}</div>
|
||
<div class="text-muted fs-xs mt-1"><i class="ti ti-clock"></i> ${e.time||""}</div>
|
||
</div>
|
||
${s?`<img src="${e.avatar}" class="avatar-md rounded-circle" alt="User">`:""}
|
||
</div>
|
||
`}).join(""),s?(s.recalculate(),(e=s.getScrollElement()).scrollTop=e.scrollHeight):this.chatContent.scrollTop=this.chatContent.scrollHeight)}sendMessage(){var e,s,t;this.chatInput&&this.activeChatId&&(e=this.chatInput.value.trim(),this.errorTimeout&&clearTimeout(this.errorTimeout),e?(this.errorElement&&(this.errorElement.classList.remove("d-block"),this.errorElement.classList.add("d-none")),(s=this.getChatById(this.activeChatId))&&(t=(new Date).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}).toLowerCase(),s.messages.push({from:"me",text:e,time:t,avatar:"assets/images/users/user-2.jpg"}),this.renderMessages(s.messages),this.chatInput.value="",this.sendButton.disabled=!0,this.simulateIncomingMessage(s.id))):this.errorElement&&(this.errorElement.textContent="Message cannot be empty.",this.errorElement.classList.remove("d-none"),this.errorElement.classList.add("d-block"),this.errorTimeout=setTimeout(()=>{this.errorElement.classList.remove("d-block"),this.errorElement.classList.add("d-none")},3e3)))}setupSearch(){this.searchInput&&this.searchInput.addEventListener("keyup",e=>{let t=e.target.value.toLowerCase();document.querySelector(".list-group").querySelectorAll(".list-group-item").forEach(e=>{var s=[...e.querySelectorAll("[data-chat-search-field]")].some(e=>e.textContent.toLowerCase().includes(t));e.style.setProperty("display",s?"":"none","important")})})}simulateIncomingMessage(s){let t=this.getChatById(s);if(t){var a=["Can't chat, calls only","😑😑😑","👍","Thanks!","Talk soon.","No worries 😄"],r=(new Date).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}).toLowerCase();let e={from:t.contact.name,text:a[Math.floor(Math.random()*a.length)],time:r,avatar:t.contact.avatar};setTimeout(()=>{t.messages.push(e),this.activeChatId===s&&this.renderMessages(t.messages)},2e3*Math.random()+1e3)}}}let chatData=[{id:"chat1",contact:{name:"Ava Thompson",avatar:"assets/images/users/user-4.jpg"},messages:[{from:"Ava Thompson",text:"Hey! Are you available for a quick call? 📞",time:"08:55 am",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Sure, give me 5 minutes. Just wrapping something up.",time:"08:57 am",avatar:"assets/images/users/user-2.jpg"},{from:"Ava Thompson",text:"Perfect. Let me know when you're ready 👍",time:"08:58 am",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Ready now. Calling you!",time:"09:00 am",avatar:"assets/images/users/user-2.jpg"},{from:"Ava Thompson",text:"Thanks for your time earlier!",time:"09:45 am",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Of course! It was a productive discussion.",time:"09:46 am",avatar:"assets/images/users/user-2.jpg"},{from:"Ava Thompson",text:"I’ll send over the updated files by noon.",time:"09:50 am",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Great, I’ll review them once they arrive.",time:"09:52 am",avatar:"assets/images/users/user-2.jpg"},{from:"Ava Thompson",text:"Just sent them via Drive. Let me know if you have issues accessing.",time:"12:03 pm",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Got them. Everything looks good so far!",time:"12:10 pm",avatar:"assets/images/users/user-2.jpg"},{from:"Ava Thompson",text:"Awesome 😊 Looking forward to your feedback!",time:"12:12 pm",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Will get back to you after lunch 🍴",time:"12:13 pm",avatar:"assets/images/users/user-2.jpg"},{from:"Ava Thompson",text:"No rush, enjoy your lunch! 😄",time:"12:14 pm",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Thanks! Talk soon.",time:"12:15 pm",avatar:"assets/images/users/user-2.jpg"}]},{id:"chat2",contact:{name:"Noah Smith",avatar:"assets/images/users/user-5.jpg"},messages:[{from:"Noah Smith",text:"Hey, quick question—did you check the latest design mockups?",time:"10:05 am",avatar:"assets/images/users/user-5.jpg"},{from:"me",text:"Not yet, just logging in now. Want me to prioritize that?",time:"10:06 am",avatar:"assets/images/users/user-2.jpg"},{from:"Noah Smith",text:"Yes please. I need your feedback before the client review at noon.",time:"10:07 am",avatar:"assets/images/users/user-5.jpg"},{from:"me",text:"Got it. I’ll go through them and send notes in a bit.",time:"10:08 am",avatar:"assets/images/users/user-2.jpg"},{from:"Noah Smith",text:"Thanks a ton!",time:"10:08 am",avatar:"assets/images/users/user-5.jpg"},{from:"me",text:"First impression: very clean. Minor spacing issues though.",time:"10:20 am",avatar:"assets/images/users/user-2.jpg"},{from:"Noah Smith",text:"Noted. Fixing those now.",time:"10:21 am",avatar:"assets/images/users/user-5.jpg"},{from:"me",text:"Sent detailed feedback via email too 📬",time:"10:25 am",avatar:"assets/images/users/user-2.jpg"},{from:"Noah Smith",text:"Got it. Appreciate the quick turnaround!",time:"10:26 am",avatar:"assets/images/users/user-5.jpg"}]},{id:"chat3",contact:{name:"Liam Turner",avatar:"assets/images/users/user-7.jpg"},messages:[{from:"Liam Turner",text:"Morning! Did you update the backend endpoints yet?",time:"09:15 am",avatar:"assets/images/users/user-7.jpg"},{from:"me",text:"Morning! Just pushed the changes to dev branch.",time:"09:16 am",avatar:"assets/images/users/user-2.jpg"},{from:"Liam Turner",text:"Awesome, I’ll pull and test on my side.",time:"09:17 am",avatar:"assets/images/users/user-7.jpg"},{from:"me",text:"Let me know if anything breaks ⚠️",time:"09:18 am",avatar:"assets/images/users/user-2.jpg"},{from:"Liam Turner",text:"Looks good so far. Just one CORS error.",time:"09:20 am",avatar:"assets/images/users/user-7.jpg"},{from:"me",text:"Ah, forgot the whitelist entry. Fixing now.",time:"09:21 am",avatar:"assets/images/users/user-2.jpg"},{from:"Liam Turner",text:"Reloaded… and it's working. All green ✅",time:"09:23 am",avatar:"assets/images/users/user-7.jpg"},{from:"me",text:"Nice! That wraps our side for this sprint then?",time:"09:24 am",avatar:"assets/images/users/user-2.jpg"},{from:"Liam Turner",text:"Yep. Good work 💪",time:"09:25 am",avatar:"assets/images/users/user-7.jpg"}]},{id:"chat4",contact:{name:"Emma Wilson",avatar:"assets/images/users/user-4.jpg"},messages:[{from:"Ava Thompson",text:"Hey! Are you available for a quick call? 📞",time:"08:55 am",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Sure, give me 5 minutes. Just wrapping something up.",time:"08:57 am",avatar:"assets/images/users/user-2.jpg"},{from:"Ava Thompson",text:"Perfect. Let me know when you're ready 👍",time:"08:58 am",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Ready now. Calling you!",time:"09:00 am",avatar:"assets/images/users/user-2.jpg"},{from:"Ava Thompson",text:"Thanks for your time earlier!",time:"09:45 am",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Of course! It was a productive discussion.",time:"09:46 am",avatar:"assets/images/users/user-2.jpg"},{from:"Ava Thompson",text:"I’ll send over the updated files by noon.",time:"09:50 am",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Great, I’ll review them once they arrive.",time:"09:52 am",avatar:"assets/images/users/user-2.jpg"}]},{id:"chat5",contact:{name:"Olivia Martinez",avatar:"assets/images/users/user-8.jpg"},messages:[{from:"Olivia Martinez",text:"Thanks a ton!",time:"10:08 am",avatar:"assets/images/users/user-8.jpg"},{from:"me",text:"First impression: very clean. Minor spacing issues though.",time:"10:20 am",avatar:"assets/images/users/user-2.jpg"},{from:"Olivia Martinez",text:"Noted. Fixing those now.",time:"10:21 am",avatar:"assets/images/users/user-8.jpg"},{from:"me",text:"Sent detailed feedback via email too 📬",time:"10:25 am",avatar:"assets/images/users/user-2.jpg"},{from:"Olivia Martinez",text:"Got it. Appreciate the quick turnaround!",time:"10:26 am",avatar:"assets/images/users/user-8.jpg"}]},{id:"chat6",contact:{name:"William Davis",avatar:"assets/images/users/user-7.jpg"},messages:[{from:"William Davis",text:"Looks good so far. Just one CORS error.",time:"09:20 am",avatar:"assets/images/users/user-7.jpg"},{from:"me",text:"Ah, forgot the whitelist entry. Fixing now.",time:"09:21 am",avatar:"assets/images/users/user-2.jpg"},{from:"William Davis",text:"Reloaded… and it's working. All green ✅",time:"09:23 am",avatar:"assets/images/users/user-7.jpg"},{from:"me",text:"Nice! That wraps our side for this sprint then?",time:"09:24 am",avatar:"assets/images/users/user-2.jpg"},{from:"William Davis",text:"Yep. Good work 💪",time:"09:25 am",avatar:"assets/images/users/user-7.jpg"}]},{id:"chat7",contact:{name:"Sophia Moore",avatar:"assets/images/users/user-10.jpg"},messages:[{from:"me",text:"Of course! It was a productive discussion.",time:"09:46 am",avatar:"assets/images/users/user-2.jpg"},{from:"Sophia Moore",text:"I’ll send over the updated files by noon.",time:"09:50 am",avatar:"assets/images/users/user-10.jpg"},{from:"me",text:"Great, I’ll review them once they arrive.",time:"09:52 am",avatar:"assets/images/users/user-2.jpg"},{from:"Sophia Moore",text:"Just sent them via Drive. Let me know if you have issues accessing.",time:"12:03 pm",avatar:"assets/images/users/user-10.jpg"},{from:"me",text:"Got them. Everything looks good so far!",time:"12:10 pm",avatar:"assets/images/users/user-2.jpg"},{from:"Sophia Moore",text:"Awesome 😊 Looking forward to your feedback!",time:"12:12 pm",avatar:"assets/images/users/user-10.jpg"},{from:"me",text:"Will get back to you after lunch 🍴",time:"12:13 pm",avatar:"assets/images/users/user-2.jpg"},{from:"Sophia Moore",text:"No rush, enjoy your lunch! 😄",time:"12:14 pm",avatar:"assets/images/users/user-10.jpg"},{from:"me",text:"Thanks! Talk soon.",time:"12:15 pm",avatar:"assets/images/users/user-2.jpg"}]},{id:"chat8",contact:{name:"Jackson Lee",avatar:"assets/images/users/user-2.jpg"},messages:[{from:"Jackson Lee",text:"Thanks a ton!",time:"10:08 am",avatar:"assets/images/users/user-2.jpg"},{from:"me",text:"First impression: very clean. Minor spacing issues though.",time:"10:20 am",avatar:"assets/images/users/user-2.jpg"},{from:"Jackson Lee",text:"Noted. Fixing those now.",time:"10:21 am",avatar:"assets/images/users/user-2.jpg"},{from:"me",text:"Sent detailed feedback via email too 📬",time:"10:25 am",avatar:"assets/images/users/user-2.jpg"},{from:"Jackson Lee",text:"Got it. Appreciate the quick turnaround!",time:"10:26 am",avatar:"assets/images/users/user-2.jpg"}]},{id:"chat9",contact:{name:"Chloe Anderson",avatar:"assets/images/users/user-3.jpg"},messages:[{from:"Chloe Anderson",text:"Looks good so far. Just one CORS error.",time:"09:20 am",avatar:"assets/images/users/user-3.jpg"},{from:"me",text:"Ah, forgot the whitelist entry. Fixing now.",time:"09:21 am",avatar:"assets/images/users/user-2.jpg"},{from:"Chloe Anderson",text:"Reloaded… and it's working. All green ✅",time:"09:23 am",avatar:"assets/images/users/user-3.jpg"},{from:"me",text:"Nice! That wraps our side for this sprint then?",time:"09:24 am",avatar:"assets/images/users/user-2.jpg"},{from:"Chloe Anderson",text:"Yep. Good work 💪",time:"09:25 am",avatar:"assets/images/users/user-3.jpg"}]},{id:"chat10",contact:{name:"Lucas Wright",avatar:"assets/images/users/user-4.jpg"},messages:[{from:"me",text:"Great, I’ll review them once they arrive.",time:"09:52 am",avatar:"assets/images/users/user-2.jpg"},{from:"Lucas Wright",text:"Just sent them via Drive. Let me know if you have issues accessing.",time:"12:03 pm",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Got them. Everything looks good so far!",time:"12:10 pm",avatar:"assets/images/users/user-2.jpg"},{from:"Lucas Wright",text:"Awesome 😊 Looking forward to your feedback!",time:"12:12 pm",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Will get back to you after lunch 🍴",time:"12:13 pm",avatar:"assets/images/users/user-2.jpg"},{from:"Lucas Wright",text:"No rush, enjoy your lunch! 😄",time:"12:14 pm",avatar:"assets/images/users/user-4.jpg"},{from:"me",text:"Thanks! Talk soon.",time:"12:15 pm",avatar:"assets/images/users/user-2.jpg"}]},{id:"chat11",contact:{name:"Mia Scott",avatar:"assets/images/users/user-6.jpg"},messages:[{from:"me",text:"First impression: very clean. Minor spacing issues though.",time:"10:20 am",avatar:"assets/images/users/user-2.jpg"},{from:"Mia Scott",text:"Noted. Fixing those now.",time:"10:21 am",avatar:"assets/images/users/user-6.jpg"},{from:"me",text:"Sent detailed feedback via email too 📬",time:"10:25 am",avatar:"assets/images/users/user-2.jpg"},{from:"Mia Scott",text:"Got it. Appreciate the quick turnaround!",time:"10:26 am",avatar:"assets/images/users/user-6.jpg"}]},{id:"chat12",contact:{name:"Benjamin Clark",avatar:"assets/images/users/user-9.jpg"},messages:[{from:"Benjamin Clark",text:"Looks good so far. Just one CORS error.",time:"09:20 am",avatar:"assets/images/users/user-9.jpg"},{from:"me",text:"Ah, forgot the whitelist entry. Fixing now.",time:"09:21 am",avatar:"assets/images/users/user-2.jpg"},{from:"Benjamin Clark",text:"Reloaded… and it's working. All green ✅",time:"09:23 am",avatar:"assets/images/users/user-9.jpg"},{from:"me",text:"Nice! That wraps our side for this sprint then?",time:"09:24 am",avatar:"assets/images/users/user-2.jpg"},{from:"Benjamin Clark",text:"Yep. Good work 💪",time:"09:25 am",avatar:"assets/images/users/user-9.jpg"}]}];document.addEventListener("DOMContentLoaded",()=>{new Chat({data:chatData})}); |