Initial commit: Luftglanz drone website with integrated AI chat assistant
Features: - Complete Luftglanz drone cleaning website - AI chat assistant integrated with OpenAI API - Expert product advice for AGO Quart and Mellerud cleaning products - Formal German language support (Sie form) - Secure PHP backend for API calls - Responsive design with mobile support - Product-specific knowledge base - Safety statements from manufacturers - Multi-page integration (index, products, services, contact) Technical components: - AI chat widget (js/ai-chat.js) - Chat styling (css/components/ai-chat.css) - Backend API (ai-chat-api.php) - Product knowledge base with detailed specifications - Demo and documentation files
This commit is contained in:
427
js/ai-chat.js
Normal file
427
js/ai-chat.js
Normal file
@@ -0,0 +1,427 @@
|
||||
// AI Chat System for Luftglanz Website
|
||||
class AIChat {
|
||||
constructor() {
|
||||
this.apiKey = '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';
|
||||
this.isOpen = false;
|
||||
this.conversationHistory = [];
|
||||
this.isTyping = false;
|
||||
|
||||
// Product knowledge base
|
||||
this.productKnowledge = `
|
||||
LUFTGLANZ PRODUCT KNOWLEDGE BASE:
|
||||
|
||||
1. COMPANY: Luftglanz - Professional drone-based roof and surface cleaning services
|
||||
|
||||
2. MAIN PRODUCTS:
|
||||
|
||||
A) AGO QUART GRÜNBELAGENTFERNER (Green algae and lichen remover)
|
||||
|
||||
PRODUCT DETAILS:
|
||||
- Name: AGO Quart Algenentferner, Grünbelag- und Flechtenentferner
|
||||
- Function: Highly effective against algae, green deposits, and lichens
|
||||
- Active period: Up to 18 months continuous protection
|
||||
- Application: Apply only on dry surfaces, no rain for 8 hours after application
|
||||
- Coverage: 0.5L bottle covers approximately 100m² surface area
|
||||
- Price: 19,90 € (39,80 € per liter)
|
||||
|
||||
MIXING RATIOS:
|
||||
- Light deposits: 1:20 with water
|
||||
- Heavy deposits (black algae, lichens): 1:10 with water
|
||||
|
||||
INGREDIENTS: Water, Benzalkonium-Chlorides, Tideceth-8, Cocamidopropyl-Betaine, Isopropyl-Alcohol
|
||||
|
||||
APPLICATION PROCESS:
|
||||
1. Apply only on dry surfaces
|
||||
2. Ensure no rain for minimum 8 hours after application
|
||||
3. Works on surface level, not suitable for moss removal in joints/cracks
|
||||
4. Cleaning duration depends on contamination severity
|
||||
5. Active for up to 18 months, provides thorough cleaning and prevents recontamination
|
||||
6. Never rinse with water after application - product must bind with surface
|
||||
|
||||
EFFECTIVENESS TIMELINE:
|
||||
- Green deposits: Disappear within days
|
||||
- Red/black algae: Several months for significant improvement
|
||||
- Heavy lichen contamination: Up to 2 years for complete removal
|
||||
|
||||
SUITABLE SURFACES: All waterproof surfaces (roofs, terraces, facades, etc.)
|
||||
IMPORTANT: AGO Quart is also SAFE for solar panels! According to the manufacturer: "Sie können die Solar-Platten bedenkenlos einsprühen. Unser AGO Quart greift dies nicht an. Es wird auch sehr erfolgreich von Firmen eingesetzt, die Solaranlagen reinigen."
|
||||
|
||||
BENEFITS:
|
||||
- No high-pressure cleaning needed
|
||||
- No scrubbing required
|
||||
- Chlorine and acid-free
|
||||
- Gentle cleaning without material damage
|
||||
- Long-term protection against recontamination
|
||||
- Self-cleaning effect through weather interaction
|
||||
|
||||
B) MELLERUD PHOTOVOLTAIK & SOLARANLAGEN REINIGER KONZENTRAT
|
||||
|
||||
PRODUCT DETAILS:
|
||||
- Name: Mellerud Photovoltaik & Solaranlagen Reiniger Konzentrat
|
||||
- Size: 0.5L concentrate
|
||||
- Price: 8,99 € (17,98 € per liter)
|
||||
- Function: Gentle and effective cleaning solution specifically for solar panels and photovoltaic systems
|
||||
- Removes: Dust, general dirt, soot residues, fine dust, and pollen
|
||||
- Special features: Streak-free, residue-free cleaning with water-repellent protection
|
||||
|
||||
MIXING RATIO:
|
||||
- Standard cleaning: 1:20 with water (ideally distilled water)
|
||||
|
||||
INGREDIENTS & SPECS:
|
||||
- Composition: Aqueous mixture of surfactants, complexing agents, and effectiveness enhancers
|
||||
- pH value: 5.70 - 6.50
|
||||
- Density: 1.020 kg/l
|
||||
|
||||
APPLICATION PROCESS:
|
||||
1. Remove coarse dirt, leaves, and debris by lightly sweeping (avoid intensive scrubbing)
|
||||
2. Mix concentrate 1:20 with water (preferably distilled water)
|
||||
3. Apply carefully with specialized solar/PV equipment, soft sponge, cloth, or squeegee
|
||||
4. Allow to work briefly
|
||||
5. Rinse thoroughly with clear water (preferably distilled water)
|
||||
|
||||
SUITABLE EQUIPMENT:
|
||||
- Specialized equipment for solar and PV systems
|
||||
- Particularly soft sponges
|
||||
- Soft cloths or squeegees
|
||||
- Avoid intensive scrubbing to prevent damage
|
||||
|
||||
BENEFITS:
|
||||
- Improves performance and lifespan of solar systems
|
||||
- Creates sustainable protection against re-contamination through water-repellent effect
|
||||
- Gentle cleaning without damage to sensitive modules
|
||||
- Streak-free and residue-free results
|
||||
- Suitable for all types of solar and PV panels
|
||||
|
||||
SAFETY INFORMATION:
|
||||
- Causes severe eye irritation
|
||||
- Keep out of reach of children
|
||||
- Wash hands thoroughly after use
|
||||
- In case of eye contact: rinse gently with water for several minutes
|
||||
- Remove contact lenses if present and continue rinsing
|
||||
- If eye irritation persists: seek medical advice
|
||||
|
||||
WHY DISTILLED WATER?
|
||||
- Minimizes residues and promotes streak-free cleaning
|
||||
- Supports optimal care of PV and solar systems
|
||||
|
||||
DRONE SERVICES:
|
||||
- Professional application using drones for hard-to-reach areas
|
||||
- Precise, even distribution of both AGO Quart and Mellerud products
|
||||
- Safe application on steep roofs and high buildings
|
||||
- Cost-effective compared to traditional scaffolding methods
|
||||
- Specialized equipment for solar panel cleaning via drone
|
||||
|
||||
SAFETY INFORMATION:
|
||||
- Use biocides safely
|
||||
- Always read labeling and product information
|
||||
- AGO Quart: Causes skin irritation (H315), serious eye damage (H318), very toxic to aquatic organisms (H410)
|
||||
- Mellerud: Causes severe eye irritation, keep away from children
|
||||
|
||||
CONTACT INFORMATION:
|
||||
AGO: AGO Sauberheit für Haus und Garten! GmbH & Co. KG, Brilloner Str. 39, 59909 Bestwig
|
||||
Phone: 02904 / 98 98 98-0, Email: info@agoshop.de
|
||||
|
||||
Mellerud: MELLERUD CHEMIE GMBH, Bernhard-Röttgen-Waldweg 20, 41379 Brüggen
|
||||
Phone: +49 (0) 2163 / 950 90 999, Email: shop@mellerud.de, experten-service@mellerud.de
|
||||
`;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.createChatWidget();
|
||||
this.attachEventListeners();
|
||||
this.loadConversationHistory();
|
||||
}
|
||||
|
||||
createChatWidget() {
|
||||
// Chat toggle button
|
||||
const chatButton = document.createElement('div');
|
||||
chatButton.id = 'ai-chat-toggle';
|
||||
chatButton.innerHTML = `
|
||||
<svg width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h4v3c0 .6.4 1 1 1 .2 0 .5-.1.7-.3L14.6 18H20c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 12h-2v-2h2v2zm0-4h-2V6h2v4z"/>
|
||||
</svg>
|
||||
<span>KI-Assistent</span>
|
||||
`;
|
||||
|
||||
// Chat window
|
||||
const chatWindow = document.createElement('div');
|
||||
chatWindow.id = 'ai-chat-window';
|
||||
chatWindow.innerHTML = `
|
||||
<div class="chat-header">
|
||||
<h3>🤖 Luftglanz KI-Assistent</h3>
|
||||
<button id="chat-close">×</button>
|
||||
</div>
|
||||
<div class="chat-messages" id="chat-messages">
|
||||
<div class="message bot-message">
|
||||
<div class="message-content">
|
||||
Hallo! Ich bin Ihr KI-Assistent für Fragen zu unseren Drohnen-Reinigungsservices und AGO Quart Produkten. Wie kann ich Ihnen helfen?
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-input-container">
|
||||
<input type="text" id="chat-input" placeholder="Stellen Sie Ihre Frage..." />
|
||||
<button id="chat-send">
|
||||
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(chatButton);
|
||||
document.body.appendChild(chatWindow);
|
||||
}
|
||||
|
||||
attachEventListeners() {
|
||||
const toggleButton = document.getElementById('ai-chat-toggle');
|
||||
const closeButton = document.getElementById('chat-close');
|
||||
const sendButton = document.getElementById('chat-send');
|
||||
const chatInput = document.getElementById('chat-input');
|
||||
|
||||
toggleButton.addEventListener('click', () => this.toggleChat());
|
||||
closeButton.addEventListener('click', () => this.closeChat());
|
||||
sendButton.addEventListener('click', () => this.sendMessage());
|
||||
|
||||
chatInput.addEventListener('keypress', (e) => {
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
this.sendMessage();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleChat() {
|
||||
this.isOpen = !this.isOpen;
|
||||
const chatWindow = document.getElementById('ai-chat-window');
|
||||
const toggleButton = document.getElementById('ai-chat-toggle');
|
||||
|
||||
if (this.isOpen) {
|
||||
chatWindow.classList.add('open');
|
||||
toggleButton.classList.add('active');
|
||||
} else {
|
||||
chatWindow.classList.remove('open');
|
||||
toggleButton.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
closeChat() {
|
||||
this.isOpen = false;
|
||||
const chatWindow = document.getElementById('ai-chat-window');
|
||||
const toggleButton = document.getElementById('ai-chat-toggle');
|
||||
|
||||
chatWindow.classList.remove('open');
|
||||
toggleButton.classList.remove('active');
|
||||
}
|
||||
|
||||
async sendMessage() {
|
||||
const input = document.getElementById('chat-input');
|
||||
const message = input.value.trim();
|
||||
|
||||
if (!message || this.isTyping) return;
|
||||
|
||||
// Add user message
|
||||
this.addMessage(message, 'user');
|
||||
input.value = '';
|
||||
|
||||
// Show typing indicator
|
||||
this.showTypingIndicator();
|
||||
|
||||
try {
|
||||
// Send to OpenAI
|
||||
const response = await this.callOpenAI(message);
|
||||
this.hideTypingIndicator();
|
||||
this.addMessage(response, 'bot');
|
||||
} catch (error) {
|
||||
this.hideTypingIndicator();
|
||||
this.addMessage('Entschuldigung, es gab einen Fehler bei der Kommunikation mit dem KI-System. Bitte versuchen Sie es erneut.', 'bot');
|
||||
console.error('OpenAI API Error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async callOpenAI(userMessage) {
|
||||
// Try PHP backend first (more secure), fallback to direct API call
|
||||
try {
|
||||
return await this.callPHPBackend(userMessage);
|
||||
} catch (error) {
|
||||
console.warn('PHP backend failed, trying direct API call:', error);
|
||||
return await this.callDirectAPI(userMessage);
|
||||
}
|
||||
}
|
||||
|
||||
async callPHPBackend(userMessage) {
|
||||
const response = await fetch('ai-chat-api.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
message: userMessage,
|
||||
history: this.conversationHistory.slice(-10) // Keep last 10 for context
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`PHP Backend error: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.success) {
|
||||
throw new Error(data.error || 'Backend error');
|
||||
}
|
||||
|
||||
// Update conversation history
|
||||
this.conversationHistory.push(
|
||||
{ role: 'user', content: userMessage },
|
||||
{ role: 'assistant', content: data.message }
|
||||
);
|
||||
|
||||
this.saveConversationHistory();
|
||||
|
||||
return data.message;
|
||||
}
|
||||
|
||||
async callDirectAPI(userMessage) {
|
||||
const systemPrompt = `Du bist ein hilfsreicher KI-Assistent für Luftglanz, ein Unternehmen für professionelle Drohnen-basierte Dach- und Oberflächenreinigung.
|
||||
|
||||
WICHTIGE ANWEISUNGEN:
|
||||
- Antworte immer auf Deutsch
|
||||
- Verwende IMMER die höfliche Anrede "Sie" (niemals "du" oder "dir")
|
||||
- Sei freundlich, professionell und hilfsbereit
|
||||
- Nutze AUSSCHLIESSLICH die bereitgestellten Produktinformationen für präzise Antworten
|
||||
- Gib konkrete Produktdetails, Preise und Anwendungshinweise aus der Wissensbasis
|
||||
- Bei Fragen zu Solaranlagen: Erkläre dass SOWOHL AGO Quart ALS AUCH Mellerud geeignet sind
|
||||
- AGO Quart: Laut Hersteller sicher für Solar-Platten, wird von Reinigungsfirmen eingesetzt
|
||||
- Mellerud: Speziell für Solaranlagen entwickelt mit schonender Formel
|
||||
- Bei Fragen zu Algen/Grünbelägen auf Dächern, empfehle AGO Quart
|
||||
- Erwähne die Vorteile der Drohnen-Anwendung wenn relevant
|
||||
- Erkläre Unterschiede zwischen den Produkten detailliert basierend auf der Wissensbasis
|
||||
- Gib konkrete Mischungsverhältnisse und Preise an
|
||||
|
||||
WICHTIG: Du kennst diese BEIDEN spezifischen Produkte sehr genau:
|
||||
1. AGO Quart (19,90€) - für Algen, Grünbeläge, Flechten auf Dächern/Terrassen
|
||||
2. Mellerud Photovoltaik Reiniger (8,99€) - speziell für Solaranlagen
|
||||
|
||||
PRODUKTWISSEN: ${this.productKnowledge}
|
||||
|
||||
Beantworte Fragen zu:
|
||||
- Unterschiede zwischen AGO Quart und Mellerud Produkten
|
||||
- Spezifische Anwendung für Solaranlagen vs. Dächer
|
||||
- Konkrete Preise, Mischungsverhältnisse und Reichweiten
|
||||
- Drohnen-Anwendung beider Produkte
|
||||
- Sicherheitshinweise für beide Produkte
|
||||
- Warum destilliertes Wasser bei Mellerud wichtig ist
|
||||
- Kontaktdaten beider Hersteller`;
|
||||
|
||||
const messages = [
|
||||
{ role: 'system', content: systemPrompt },
|
||||
...this.conversationHistory.slice(-10), // Keep last 10 messages for context
|
||||
{ role: 'user', content: userMessage }
|
||||
];
|
||||
|
||||
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${this.apiKey}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: 'gpt-3.5-turbo',
|
||||
messages: messages,
|
||||
max_tokens: 500,
|
||||
temperature: 0.7,
|
||||
presence_penalty: 0.1,
|
||||
frequency_penalty: 0.1
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`OpenAI API error: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const assistantMessage = data.choices[0].message.content;
|
||||
|
||||
// Update conversation history
|
||||
this.conversationHistory.push(
|
||||
{ role: 'user', content: userMessage },
|
||||
{ role: 'assistant', content: assistantMessage }
|
||||
);
|
||||
|
||||
this.saveConversationHistory();
|
||||
|
||||
return assistantMessage;
|
||||
}
|
||||
|
||||
addMessage(content, sender) {
|
||||
const messagesContainer = document.getElementById('chat-messages');
|
||||
const messageDiv = document.createElement('div');
|
||||
messageDiv.className = `message ${sender}-message`;
|
||||
|
||||
const messageContent = document.createElement('div');
|
||||
messageContent.className = 'message-content';
|
||||
messageContent.textContent = content;
|
||||
|
||||
messageDiv.appendChild(messageContent);
|
||||
messagesContainer.appendChild(messageDiv);
|
||||
|
||||
// Auto-scroll to bottom
|
||||
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
||||
}
|
||||
|
||||
showTypingIndicator() {
|
||||
this.isTyping = true;
|
||||
const messagesContainer = document.getElementById('chat-messages');
|
||||
|
||||
const typingDiv = document.createElement('div');
|
||||
typingDiv.id = 'typing-indicator';
|
||||
typingDiv.className = 'message bot-message typing';
|
||||
typingDiv.innerHTML = `
|
||||
<div class="message-content">
|
||||
<div class="typing-dots">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
messagesContainer.appendChild(typingDiv);
|
||||
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
||||
}
|
||||
|
||||
hideTypingIndicator() {
|
||||
this.isTyping = false;
|
||||
const typingIndicator = document.getElementById('typing-indicator');
|
||||
if (typingIndicator) {
|
||||
typingIndicator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
saveConversationHistory() {
|
||||
try {
|
||||
localStorage.setItem('luftglanz_chat_history', JSON.stringify(this.conversationHistory));
|
||||
} catch (error) {
|
||||
console.warn('Could not save conversation history:', error);
|
||||
}
|
||||
}
|
||||
|
||||
loadConversationHistory() {
|
||||
try {
|
||||
const saved = localStorage.getItem('luftglanz_chat_history');
|
||||
if (saved) {
|
||||
this.conversationHistory = JSON.parse(saved);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Could not load conversation history:', error);
|
||||
this.conversationHistory = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize chat when DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
window.aiChat = new AIChat();
|
||||
});
|
||||
Reference in New Issue
Block a user