922 lines
29 KiB
JavaScript
922 lines
29 KiB
JavaScript
/**
|
|
* Kasico Chat Widget - Furry-Style Live-Chat
|
|
* WebSocket-basiertes Chat-System
|
|
*/
|
|
|
|
class KasicoChatWidget {
|
|
constructor() {
|
|
this.isOpen = false;
|
|
this.isConnected = false;
|
|
this.currentRoom = null;
|
|
this.websocket = null;
|
|
this.notificationSocket = null;
|
|
this.typingTimeout = null;
|
|
this.unreadCount = 0;
|
|
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
// Chat-Widget HTML erstellen
|
|
this.createWidget();
|
|
|
|
// Event Listeners
|
|
this.bindEvents();
|
|
|
|
// WebSocket-Verbindung
|
|
this.connectWebSocket();
|
|
|
|
// Auto-Show nach 30 Sekunden
|
|
setTimeout(() => {
|
|
if (!this.isOpen && !this.hasInteracted()) {
|
|
this.showWelcomeMessage();
|
|
}
|
|
}, 30000);
|
|
}
|
|
|
|
createWidget() {
|
|
const widgetHTML = `
|
|
<div id="kasico-chat-widget" class="chat-widget">
|
|
<!-- Chat Button -->
|
|
<div class="chat-button" id="chat-button">
|
|
<div class="chat-button-icon">
|
|
<i class="fas fa-comments"></i>
|
|
<span class="chat-notification-badge" id="chat-notification-badge" style="display: none;">0</span>
|
|
</div>
|
|
<div class="chat-button-text">
|
|
<span class="chat-button-title">Chat</span>
|
|
<span class="chat-button-subtitle">Online</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chat Window -->
|
|
<div class="chat-window" id="chat-window">
|
|
<!-- Chat Header -->
|
|
<div class="chat-header">
|
|
<div class="chat-header-info">
|
|
<div class="chat-avatar">
|
|
<img src="/static/images/dog-user-icon.svg" alt="Kasico Support">
|
|
</div>
|
|
<div class="chat-header-text">
|
|
<h4>Kasico Support</h4>
|
|
<span class="chat-status online">Online</span>
|
|
</div>
|
|
</div>
|
|
<div class="chat-header-actions">
|
|
<button class="chat-minimize" id="chat-minimize">
|
|
<i class="fas fa-minus"></i>
|
|
</button>
|
|
<button class="chat-close" id="chat-close">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chat Messages -->
|
|
<div class="chat-messages" id="chat-messages">
|
|
<div class="chat-welcome">
|
|
<div class="chat-welcome-icon">
|
|
<i class="fas fa-paw"></i>
|
|
</div>
|
|
<h5>Willkommen bei Kasico! 🐾</h5>
|
|
<p>Wie können wir dir heute helfen?</p>
|
|
<div class="chat-quick-actions">
|
|
<button class="quick-action" data-action="pricing">
|
|
<i class="fas fa-tag"></i> Preise
|
|
</button>
|
|
<button class="quick-action" data-action="custom-order">
|
|
<i class="fas fa-magic"></i> Custom Order
|
|
</button>
|
|
<button class="quick-action" data-action="shipping">
|
|
<i class="fas fa-shipping-fast"></i> Versand
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chat Input -->
|
|
<div class="chat-input-container">
|
|
<div class="chat-input-wrapper">
|
|
<textarea
|
|
class="chat-input"
|
|
id="chat-input"
|
|
placeholder="Schreibe eine Nachricht..."
|
|
rows="1"
|
|
></textarea>
|
|
<div class="chat-input-actions">
|
|
<button class="chat-attachment" id="chat-attachment">
|
|
<i class="fas fa-paperclip"></i>
|
|
</button>
|
|
<button class="chat-send" id="chat-send">
|
|
<i class="fas fa-paper-plane"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="chat-typing" id="chat-typing" style="display: none;">
|
|
<span class="typing-indicator">
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</span>
|
|
<span class="typing-text">Support schreibt...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- File Upload Input -->
|
|
<input type="file" id="chat-file-input" accept="image/*,.pdf,.doc,.docx" style="display: none;">
|
|
</div>
|
|
`;
|
|
|
|
document.body.insertAdjacentHTML('beforeend', widgetHTML);
|
|
|
|
// CSS hinzufügen
|
|
this.addStyles();
|
|
}
|
|
|
|
addStyles() {
|
|
const styles = `
|
|
.chat-widget {
|
|
position: fixed;
|
|
bottom: 20px;
|
|
right: 20px;
|
|
z-index: 1000;
|
|
font-family: 'Quicksand', sans-serif;
|
|
}
|
|
|
|
.chat-button {
|
|
background: linear-gradient(135deg, #FF6B9D, #FF8E53);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 25px;
|
|
padding: 15px 20px;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
box-shadow: 0 4px 20px rgba(255, 107, 157, 0.3);
|
|
transition: all 0.3s ease;
|
|
min-width: 200px;
|
|
}
|
|
|
|
.chat-button:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 6px 25px rgba(255, 107, 157, 0.4);
|
|
}
|
|
|
|
.chat-button-icon {
|
|
position: relative;
|
|
font-size: 20px;
|
|
}
|
|
|
|
.chat-notification-badge {
|
|
position: absolute;
|
|
top: -8px;
|
|
right: -8px;
|
|
background: #FF4757;
|
|
color: white;
|
|
border-radius: 50%;
|
|
width: 20px;
|
|
height: 20px;
|
|
font-size: 12px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.chat-button-text {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.chat-button-title {
|
|
font-weight: 600;
|
|
font-size: 16px;
|
|
}
|
|
|
|
.chat-button-subtitle {
|
|
font-size: 12px;
|
|
opacity: 0.9;
|
|
}
|
|
|
|
.chat-window {
|
|
position: absolute;
|
|
bottom: 80px;
|
|
right: 0;
|
|
width: 350px;
|
|
height: 500px;
|
|
background: white;
|
|
border-radius: 20px;
|
|
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
|
|
display: none;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
border: 2px solid #FF6B9D;
|
|
}
|
|
|
|
.chat-header {
|
|
background: linear-gradient(135deg, #FF6B9D, #FF8E53);
|
|
color: white;
|
|
padding: 15px 20px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.chat-header-info {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
|
|
.chat-avatar {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 50%;
|
|
overflow: hidden;
|
|
border: 2px solid white;
|
|
}
|
|
|
|
.chat-avatar img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.chat-header-text h4 {
|
|
margin: 0;
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.chat-status {
|
|
font-size: 12px;
|
|
opacity: 0.9;
|
|
}
|
|
|
|
.chat-status.online::before {
|
|
content: '';
|
|
display: inline-block;
|
|
width: 8px;
|
|
height: 8px;
|
|
background: #2ED573;
|
|
border-radius: 50%;
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.chat-header-actions {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
|
|
.chat-header-actions button {
|
|
background: rgba(255, 255, 255, 0.2);
|
|
border: none;
|
|
color: white;
|
|
width: 30px;
|
|
height: 30px;
|
|
border-radius: 50%;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.chat-header-actions button:hover {
|
|
background: rgba(255, 255, 255, 0.3);
|
|
}
|
|
|
|
.chat-messages {
|
|
flex: 1;
|
|
padding: 20px;
|
|
overflow-y: auto;
|
|
background: #F8F9FA;
|
|
}
|
|
|
|
.chat-welcome {
|
|
text-align: center;
|
|
padding: 20px;
|
|
background: white;
|
|
border-radius: 15px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.chat-welcome-icon {
|
|
font-size: 40px;
|
|
color: #FF6B9D;
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.chat-welcome h5 {
|
|
margin: 0 0 10px 0;
|
|
color: #333;
|
|
}
|
|
|
|
.chat-welcome p {
|
|
margin: 0 0 20px 0;
|
|
color: #666;
|
|
}
|
|
|
|
.chat-quick-actions {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.quick-action {
|
|
background: linear-gradient(135deg, #FF6B9D, #FF8E53);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 20px;
|
|
padding: 10px 15px;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
transition: all 0.3s ease;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.quick-action:hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 4px 15px rgba(255, 107, 157, 0.3);
|
|
}
|
|
|
|
.chat-message {
|
|
margin-bottom: 15px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.chat-message.sent {
|
|
align-items: flex-end;
|
|
}
|
|
|
|
.chat-message.received {
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.chat-message.system {
|
|
align-items: center;
|
|
}
|
|
|
|
.message-bubble {
|
|
max-width: 80%;
|
|
padding: 12px 16px;
|
|
border-radius: 20px;
|
|
font-size: 14px;
|
|
line-height: 1.4;
|
|
position: relative;
|
|
}
|
|
|
|
.message-bubble.sent {
|
|
background: linear-gradient(135deg, #FF6B9D, #FF8E53);
|
|
color: white;
|
|
border-bottom-right-radius: 5px;
|
|
}
|
|
|
|
.message-bubble.received {
|
|
background: white;
|
|
color: #333;
|
|
border: 1px solid #E9ECEF;
|
|
border-bottom-left-radius: 5px;
|
|
}
|
|
|
|
.message-bubble.system {
|
|
background: #F8F9FA;
|
|
color: #666;
|
|
font-size: 12px;
|
|
font-style: italic;
|
|
border-radius: 15px;
|
|
}
|
|
|
|
.message-time {
|
|
font-size: 11px;
|
|
opacity: 0.7;
|
|
margin-top: 5px;
|
|
}
|
|
|
|
.message-time.sent {
|
|
text-align: right;
|
|
}
|
|
|
|
.message-time.received {
|
|
text-align: left;
|
|
}
|
|
|
|
.message-time.system {
|
|
text-align: center;
|
|
}
|
|
|
|
.chat-input-container {
|
|
padding: 15px 20px;
|
|
background: white;
|
|
border-top: 1px solid #E9ECEF;
|
|
}
|
|
|
|
.chat-input-wrapper {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
gap: 10px;
|
|
}
|
|
|
|
.chat-input {
|
|
flex: 1;
|
|
border: 1px solid #E9ECEF;
|
|
border-radius: 20px;
|
|
padding: 12px 16px;
|
|
font-size: 14px;
|
|
resize: none;
|
|
outline: none;
|
|
transition: border-color 0.3s ease;
|
|
font-family: inherit;
|
|
}
|
|
|
|
.chat-input:focus {
|
|
border-color: #FF6B9D;
|
|
}
|
|
|
|
.chat-input-actions {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
|
|
.chat-input-actions button {
|
|
background: linear-gradient(135deg, #FF6B9D, #FF8E53);
|
|
color: white;
|
|
border: none;
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 50%;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.chat-input-actions button:hover {
|
|
transform: scale(1.1);
|
|
}
|
|
|
|
.chat-input-actions button:disabled {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.chat-typing {
|
|
padding: 10px 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
color: #666;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.typing-indicator {
|
|
display: flex;
|
|
gap: 3px;
|
|
}
|
|
|
|
.typing-indicator span {
|
|
width: 6px;
|
|
height: 6px;
|
|
background: #FF6B9D;
|
|
border-radius: 50%;
|
|
animation: typing 1.4s infinite ease-in-out;
|
|
}
|
|
|
|
.typing-indicator span:nth-child(1) { animation-delay: -0.32s; }
|
|
.typing-indicator span:nth-child(2) { animation-delay: -0.16s; }
|
|
|
|
@keyframes typing {
|
|
0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }
|
|
40% { transform: scale(1); opacity: 1; }
|
|
}
|
|
|
|
.chat-widget.hidden .chat-window {
|
|
display: none;
|
|
}
|
|
|
|
.chat-widget.open .chat-window {
|
|
display: flex;
|
|
}
|
|
|
|
/* Responsive Design */
|
|
@media (max-width: 768px) {
|
|
.chat-widget {
|
|
bottom: 10px;
|
|
right: 10px;
|
|
}
|
|
|
|
.chat-window {
|
|
width: calc(100vw - 20px);
|
|
height: calc(100vh - 100px);
|
|
bottom: 70px;
|
|
}
|
|
|
|
.chat-button {
|
|
min-width: auto;
|
|
padding: 12px 15px;
|
|
}
|
|
|
|
.chat-button-text {
|
|
display: none;
|
|
}
|
|
}
|
|
`;
|
|
|
|
const styleSheet = document.createElement('style');
|
|
styleSheet.textContent = styles;
|
|
document.head.appendChild(styleSheet);
|
|
}
|
|
|
|
bindEvents() {
|
|
// Chat Button
|
|
document.getElementById('chat-button').addEventListener('click', () => {
|
|
this.toggleChat();
|
|
});
|
|
|
|
// Chat Controls
|
|
document.getElementById('chat-minimize').addEventListener('click', () => {
|
|
this.toggleChat();
|
|
});
|
|
|
|
document.getElementById('chat-close').addEventListener('click', () => {
|
|
this.closeChat();
|
|
});
|
|
|
|
// Chat Input
|
|
const chatInput = document.getElementById('chat-input');
|
|
chatInput.addEventListener('keypress', (e) => {
|
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
e.preventDefault();
|
|
this.sendMessage();
|
|
}
|
|
});
|
|
|
|
chatInput.addEventListener('input', () => {
|
|
this.adjustTextareaHeight(chatInput);
|
|
this.sendTypingIndicator(true);
|
|
});
|
|
|
|
// Send Button
|
|
document.getElementById('chat-send').addEventListener('click', () => {
|
|
this.sendMessage();
|
|
});
|
|
|
|
// Attachment Button
|
|
document.getElementById('chat-attachment').addEventListener('click', () => {
|
|
document.getElementById('chat-file-input').click();
|
|
});
|
|
|
|
// File Upload
|
|
document.getElementById('chat-file-input').addEventListener('change', (e) => {
|
|
this.handleFileUpload(e.target.files[0]);
|
|
});
|
|
|
|
// Quick Actions
|
|
document.querySelectorAll('.quick-action').forEach(button => {
|
|
button.addEventListener('click', (e) => {
|
|
const action = e.target.closest('.quick-action').dataset.action;
|
|
this.handleQuickAction(action);
|
|
});
|
|
});
|
|
}
|
|
|
|
connectWebSocket() {
|
|
// Chat WebSocket
|
|
this.connectChatWebSocket();
|
|
|
|
// Notification WebSocket
|
|
this.connectNotificationWebSocket();
|
|
}
|
|
|
|
connectChatWebSocket() {
|
|
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
const wsUrl = `${protocol}//${window.location.host}/ws/chat/${this.currentRoom || 'new'}/`;
|
|
|
|
this.websocket = new WebSocket(wsUrl);
|
|
|
|
this.websocket.onopen = () => {
|
|
console.log('Chat WebSocket connected');
|
|
this.isConnected = true;
|
|
this.updateConnectionStatus(true);
|
|
};
|
|
|
|
this.websocket.onmessage = (event) => {
|
|
const data = JSON.parse(event.data);
|
|
this.handleWebSocketMessage(data);
|
|
};
|
|
|
|
this.websocket.onclose = () => {
|
|
console.log('Chat WebSocket disconnected');
|
|
this.isConnected = false;
|
|
this.updateConnectionStatus(false);
|
|
|
|
// Reconnect nach 5 Sekunden
|
|
setTimeout(() => {
|
|
if (!this.isConnected) {
|
|
this.connectChatWebSocket();
|
|
}
|
|
}, 5000);
|
|
};
|
|
|
|
this.websocket.onerror = (error) => {
|
|
console.error('Chat WebSocket error:', error);
|
|
};
|
|
}
|
|
|
|
connectNotificationWebSocket() {
|
|
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
const wsUrl = `${protocol}//${window.location.host}/ws/notifications/`;
|
|
|
|
this.notificationSocket = new WebSocket(wsUrl);
|
|
|
|
this.notificationSocket.onopen = () => {
|
|
console.log('Notification WebSocket connected');
|
|
};
|
|
|
|
this.notificationSocket.onmessage = (event) => {
|
|
const data = JSON.parse(event.data);
|
|
this.handleNotificationMessage(data);
|
|
};
|
|
}
|
|
|
|
handleWebSocketMessage(data) {
|
|
switch (data.type) {
|
|
case 'message':
|
|
this.addMessage(data.message);
|
|
break;
|
|
case 'typing':
|
|
this.showTypingIndicator(data.user, data.typing);
|
|
break;
|
|
case 'read':
|
|
this.markMessagesAsRead(data.user_id);
|
|
break;
|
|
case 'system':
|
|
this.addSystemMessage(data.message);
|
|
break;
|
|
case 'error':
|
|
this.showError(data.message);
|
|
break;
|
|
}
|
|
}
|
|
|
|
handleNotificationMessage(data) {
|
|
if (data.type === 'notification') {
|
|
this.showNotification(data.notification);
|
|
}
|
|
}
|
|
|
|
sendMessage() {
|
|
const input = document.getElementById('chat-input');
|
|
const message = input.value.trim();
|
|
|
|
if (!message || !this.isConnected) return;
|
|
|
|
// Nachricht senden
|
|
this.websocket.send(JSON.stringify({
|
|
type: 'message',
|
|
content: message,
|
|
message_type: 'text'
|
|
}));
|
|
|
|
// Input leeren
|
|
input.value = '';
|
|
this.adjustTextareaHeight(input);
|
|
|
|
// Typing Indicator stoppen
|
|
this.sendTypingIndicator(false);
|
|
}
|
|
|
|
sendTypingIndicator(typing) {
|
|
if (this.typingTimeout) {
|
|
clearTimeout(this.typingTimeout);
|
|
}
|
|
|
|
if (typing) {
|
|
this.websocket.send(JSON.stringify({
|
|
type: 'typing',
|
|
typing: true
|
|
}));
|
|
|
|
this.typingTimeout = setTimeout(() => {
|
|
this.sendTypingIndicator(false);
|
|
}, 3000);
|
|
} else {
|
|
this.websocket.send(JSON.stringify({
|
|
type: 'typing',
|
|
typing: false
|
|
}));
|
|
}
|
|
}
|
|
|
|
addMessage(message) {
|
|
const messagesContainer = document.getElementById('chat-messages');
|
|
const messageDiv = document.createElement('div');
|
|
|
|
const isOwnMessage = message.sender_id === this.getCurrentUserId();
|
|
const messageClass = isOwnMessage ? 'sent' : 'received';
|
|
|
|
messageDiv.className = `chat-message ${messageClass}`;
|
|
|
|
let messageContent = '';
|
|
|
|
if (message.message_type === 'image') {
|
|
messageContent = `<img src="${message.image_url}" alt="Bild" style="max-width: 200px; border-radius: 10px;">`;
|
|
} else if (message.message_type === 'file') {
|
|
messageContent = `<div class="file-message">
|
|
<i class="fas fa-file"></i>
|
|
<span>${message.content}</span>
|
|
</div>`;
|
|
} else {
|
|
messageContent = message.content;
|
|
}
|
|
|
|
messageDiv.innerHTML = `
|
|
<div class="message-bubble ${messageClass}">
|
|
${messageContent}
|
|
</div>
|
|
<div class="message-time ${messageClass}">
|
|
${this.formatTime(message.created_at)}
|
|
</div>
|
|
`;
|
|
|
|
messagesContainer.appendChild(messageDiv);
|
|
this.scrollToBottom();
|
|
|
|
// Notification Badge aktualisieren
|
|
if (!isOwnMessage && !this.isOpen) {
|
|
this.incrementUnreadCount();
|
|
}
|
|
}
|
|
|
|
addSystemMessage(message) {
|
|
const messagesContainer = document.getElementById('chat-messages');
|
|
const messageDiv = document.createElement('div');
|
|
|
|
messageDiv.className = 'chat-message system';
|
|
messageDiv.innerHTML = `
|
|
<div class="message-bubble system">
|
|
${message}
|
|
</div>
|
|
<div class="message-time system">
|
|
${this.formatTime(new Date())}
|
|
</div>
|
|
`;
|
|
|
|
messagesContainer.appendChild(messageDiv);
|
|
this.scrollToBottom();
|
|
}
|
|
|
|
showTypingIndicator(user, typing) {
|
|
const typingElement = document.getElementById('chat-typing');
|
|
|
|
if (typing) {
|
|
typingElement.style.display = 'flex';
|
|
} else {
|
|
typingElement.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
showWelcomeMessage() {
|
|
this.addSystemMessage('Willkommen! Wie können wir dir helfen? 🐾');
|
|
}
|
|
|
|
handleQuickAction(action) {
|
|
const messages = {
|
|
'pricing': 'Hier findest du unsere Preise: https://kasico.de/pricing',
|
|
'custom-order': 'Für Custom Orders: https://kasico.de/custom-order',
|
|
'shipping': 'Versandinfo: https://kasico.de/shipping'
|
|
};
|
|
|
|
this.addMessage({
|
|
sender_id: this.getCurrentUserId(),
|
|
content: messages[action],
|
|
message_type: 'text',
|
|
created_at: new Date().toISOString()
|
|
});
|
|
|
|
// Nachricht senden
|
|
this.websocket.send(JSON.stringify({
|
|
type: 'message',
|
|
content: messages[action],
|
|
message_type: 'text'
|
|
}));
|
|
}
|
|
|
|
handleFileUpload(file) {
|
|
if (!file) return;
|
|
|
|
// Datei-Upload simulieren (in Produktion würde hier ein echter Upload stattfinden)
|
|
const fileUrl = URL.createObjectURL(file);
|
|
|
|
this.websocket.send(JSON.stringify({
|
|
type: 'file_upload',
|
|
file_url: fileUrl,
|
|
filename: file.name,
|
|
file_type: file.type.startsWith('image/') ? 'image' : 'file'
|
|
}));
|
|
}
|
|
|
|
toggleChat() {
|
|
const widget = document.getElementById('kasico-chat-widget');
|
|
|
|
if (this.isOpen) {
|
|
widget.classList.remove('open');
|
|
this.isOpen = false;
|
|
} else {
|
|
widget.classList.add('open');
|
|
this.isOpen = true;
|
|
this.clearUnreadCount();
|
|
this.scrollToBottom();
|
|
}
|
|
}
|
|
|
|
closeChat() {
|
|
const widget = document.getElementById('kasico-chat-widget');
|
|
widget.classList.remove('open');
|
|
this.isOpen = false;
|
|
}
|
|
|
|
updateConnectionStatus(connected) {
|
|
const statusElement = document.querySelector('.chat-status');
|
|
const button = document.getElementById('chat-button');
|
|
|
|
if (connected) {
|
|
statusElement.textContent = 'Online';
|
|
statusElement.className = 'chat-status online';
|
|
button.style.opacity = '1';
|
|
} else {
|
|
statusElement.textContent = 'Offline';
|
|
statusElement.className = 'chat-status offline';
|
|
button.style.opacity = '0.7';
|
|
}
|
|
}
|
|
|
|
incrementUnreadCount() {
|
|
this.unreadCount++;
|
|
const badge = document.getElementById('chat-notification-badge');
|
|
badge.textContent = this.unreadCount;
|
|
badge.style.display = 'flex';
|
|
}
|
|
|
|
clearUnreadCount() {
|
|
this.unreadCount = 0;
|
|
const badge = document.getElementById('chat-notification-badge');
|
|
badge.style.display = 'none';
|
|
}
|
|
|
|
scrollToBottom() {
|
|
const messagesContainer = document.getElementById('chat-messages');
|
|
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
|
}
|
|
|
|
adjustTextareaHeight(textarea) {
|
|
textarea.style.height = 'auto';
|
|
textarea.style.height = Math.min(textarea.scrollHeight, 100) + 'px';
|
|
}
|
|
|
|
formatTime(timestamp) {
|
|
const date = new Date(timestamp);
|
|
return date.toLocaleTimeString('de-DE', {
|
|
hour: '2-digit',
|
|
minute: '2-digit'
|
|
});
|
|
}
|
|
|
|
getCurrentUserId() {
|
|
// In einer echten Implementierung würde hier die User-ID aus dem Session/Token geholt
|
|
return 1; // Placeholder
|
|
}
|
|
|
|
hasInteracted() {
|
|
// Prüfen ob User bereits mit der Seite interagiert hat
|
|
return sessionStorage.getItem('chat_interaction') === 'true';
|
|
}
|
|
|
|
showError(message) {
|
|
this.addSystemMessage(`Fehler: ${message}`);
|
|
}
|
|
|
|
showNotification(notification) {
|
|
// Browser Notification anzeigen
|
|
if ('Notification' in window && Notification.permission === 'granted') {
|
|
new Notification(notification.title, {
|
|
body: notification.message,
|
|
icon: '/static/images/kasico-logo.png'
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// Chat Widget initialisieren
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
window.kasicoChat = new KasicoChatWidget();
|
|
|
|
// Notification Permission anfordern
|
|
if ('Notification' in window && Notification.permission === 'default') {
|
|
Notification.requestPermission();
|
|
}
|
|
});
|