Initial commit on develop branch
This commit is contained in:
commit
aa24ed3be9
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
DEDICATED JAVASCRIPT FOR AIMOJSTER.SI CHATBOT WIDGET
|
||||
Last Updated: 16. September 2025 (v8.0 - Final Production Version)
|
||||
Author: Gemini AI for AIMojster.si
|
||||
|
||||
This is the final, clean production version of the chatbot script.
|
||||
It reliably creates, stores (per session), and sends a unique session ID with every user message,
|
||||
ensuring that the n8n workflow functions correctly.
|
||||
*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// --- DOM ELEMENTI ---
|
||||
const chatWidgetButton = document.getElementById('chat-widget-button');
|
||||
const chatContainer = document.getElementById('chat-widget-container');
|
||||
const closeChatBtn = document.getElementById('close-chat-btn');
|
||||
const chatMessagesContainer = document.getElementById('chat-messages');
|
||||
const chatInputForm = document.getElementById('chat-input-form');
|
||||
const chatInputField = document.getElementById('chat-input');
|
||||
|
||||
// --- KONFIGURACIJA ---
|
||||
const N8N_WEBHOOK_URL = 'https://n8n.spletnimojster.si/webhook/joze/chat';
|
||||
|
||||
// Preverimo, ali obstajajo vsi potrebni HTML elementi za delovanje.
|
||||
if (!chatWidgetButton || !chatContainer || !chatInputForm) {
|
||||
console.error("Chatbot HTML elements could not be found. The script will not initialize.");
|
||||
return;
|
||||
}
|
||||
|
||||
// ====================================================================== //
|
||||
// === UPRAVLJANJE S SEJO (SESSION ID MANAGEMENT) === //
|
||||
// ====================================================================== //
|
||||
|
||||
/**
|
||||
* Zanesljivo pridobi ali ustvari unikaten Session ID za trenutni pogovor.
|
||||
* Uporablja `sessionStorage`, kar pomeni, da ID obstane med osveževanjem strani,
|
||||
* a se ponastavi, ko uporabnik zapre zavihek brskalnika.
|
||||
* @returns {string} The unique session ID for the current chat session.
|
||||
*/
|
||||
function getSessionId() {
|
||||
const SESSION_KEY = 'aimojster_chatbot_session_id'; // Uporabimo unikatno ime ključa
|
||||
let sessionId = sessionStorage.getItem(SESSION_KEY);
|
||||
|
||||
if (!sessionId) {
|
||||
// crypto.randomUUID() je moderen, varen in standarden način za generiranje UUID-jev.
|
||||
sessionId = crypto.randomUUID();
|
||||
sessionStorage.setItem(SESSION_KEY, sessionId);
|
||||
}
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
// ====================================================================== //
|
||||
// === KOMUNIKACIJA Z N8N === //
|
||||
// ====================================================================== //
|
||||
|
||||
/**
|
||||
* Sestavi in pošlje uporabnikovo sporočilo skupaj s session ID-jem na n8n webhook.
|
||||
* @param {string} userMessage - Sporočilo, ki ga je vnesel uporabnik.
|
||||
*/
|
||||
async function sendMessageToBot(userMessage) {
|
||||
showTypingIndicator();
|
||||
|
||||
// Pridobimo ali ustvarimo session ID za to sejo.
|
||||
const currentSessionId = getSessionId();
|
||||
|
||||
// Sestavimo pravilen objekt (payload), ki ga n8n pričakuje.
|
||||
const payload = {
|
||||
sessionId: currentSessionId,
|
||||
chatInput: userMessage,
|
||||
action: "sendMessage"
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(N8N_WEBHOOK_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Server returned status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const botReply = data.output;
|
||||
|
||||
if (botReply) {
|
||||
addBotMessageToUI(botReply);
|
||||
} else {
|
||||
// To se zgodi, če n8n vrne prazen odgovor ali napačno strukturo.
|
||||
console.error("Response from bot was empty or in a malformed structure.", data);
|
||||
throw new Error("Malformed response from server.");
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error communicating with the chatbot API:', error);
|
||||
addBotMessageToUI("Oprostite, prišlo je do tehnične napake. Poskusite znova kasneje.");
|
||||
}
|
||||
}
|
||||
|
||||
// ====================================================================== //
|
||||
// === UPRAVLJANJE Z UI IN DOGODKI === //
|
||||
// ====================================================================== //
|
||||
|
||||
// --- Pomožne UI funkcije ---
|
||||
function openChatWidget() {
|
||||
chatContainer.classList.remove('hidden');
|
||||
chatInputField.focus();
|
||||
}
|
||||
|
||||
function closeChatWidget() {
|
||||
chatContainer.classList.add('hidden');
|
||||
}
|
||||
|
||||
function addMessageToUI(text, sender) {
|
||||
const messageElement = document.createElement('div');
|
||||
messageElement.classList.add('chat-message', `${sender}-message`);
|
||||
messageElement.textContent = text;
|
||||
chatMessagesContainer.appendChild(messageElement);
|
||||
chatMessagesContainer.scrollTop = chatMessagesContainer.scrollHeight;
|
||||
}
|
||||
|
||||
function showTypingIndicator() {
|
||||
if (chatMessagesContainer.querySelector('.typing-indicator')) return;
|
||||
const indicator = document.createElement('div');
|
||||
indicator.classList.add('chat-message', 'bot-message', 'typing-indicator');
|
||||
indicator.innerHTML = '<span>.</span><span>.</span><span>.</span>';
|
||||
chatMessagesContainer.appendChild(indicator);
|
||||
chatMessagesContainer.scrollTop = chatMessagesContainer.scrollHeight;
|
||||
}
|
||||
|
||||
function hideTypingIndicator() {
|
||||
const indicator = chatMessagesContainer.querySelector('.typing-indicator');
|
||||
if (indicator) indicator.remove();
|
||||
}
|
||||
|
||||
const addUserMessageToUI = (message) => addMessageToUI(message, 'user');
|
||||
const addBotMessageToUI = (message) => {
|
||||
hideTypingIndicator();
|
||||
addMessageToUI(message, 'bot');
|
||||
};
|
||||
|
||||
// --- Glavni Event Listener za oddajo sporočila ---
|
||||
chatInputForm.addEventListener('submit', function(event) {
|
||||
event.preventDefault();
|
||||
const userMessage = chatInputField.value.trim();
|
||||
|
||||
if (userMessage) {
|
||||
addUserMessageToUI(userMessage);
|
||||
sendMessageToBot(userMessage);
|
||||
chatInputField.value = '';
|
||||
}
|
||||
});
|
||||
|
||||
// --- Event Listenerji za odpiranje in zapiranje okna ---
|
||||
chatWidgetButton.addEventListener('click', openChatWidget);
|
||||
closeChatBtn.addEventListener('click', closeChatWidget);
|
||||
|
||||
console.log("Chatbot v8.0 (Final Production) initialized successfully.");
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,155 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="sl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>n8n Webhook Debugger (Popravljena Verzija)</title>
|
||||
<style>
|
||||
body { font-family: sans-serif; line-height: 1.6; padding: 20px; background-color: #f4f4f4; }
|
||||
h1 { color: #333; }
|
||||
p { color: #555; }
|
||||
strong { color: #0066cc; }
|
||||
button { font-size: 16px; padding: 10px 15px; margin: 5px; cursor: pointer; border: 1px solid #ccc; border-radius: 5px; }
|
||||
button#test-post-json { background-color: #d4edda; border-color: #c3e6cb;}
|
||||
button:hover { background-color: #e9e9e9; }
|
||||
#results {
|
||||
white-space: pre-wrap;
|
||||
background-color: #2d2d2d;
|
||||
color: #
|
||||
;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
margin-top: 20px;
|
||||
max-height: 600px;
|
||||
overflow-y: auto;
|
||||
font-family: monospace;
|
||||
font-size: 14px;
|
||||
}
|
||||
.success { color: #28a745; font-weight: bold; }
|
||||
.error { color: #dc3545; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>n8n Webhook Debugger (Popravljena Verzija)</h1>
|
||||
<p>Ta stran bo testirala klic na vaš n8n webhook s <strong>pravilnim formatom podatkov</strong>.</p>
|
||||
<p>Pričakujemo, da bo <strong>Test 1</strong> zdaj uspešen in vrnil `Status: 200 OK`.</p>
|
||||
|
||||
<div>
|
||||
<button id="test-post-json">1. Testiraj POST z JSON (Pravilen format)</button>
|
||||
<button id="test-get">2. Testiraj GET</button>
|
||||
<button id="test-post-form">3. Testiraj POST z Form Data (Pravilen format)</button>
|
||||
</div>
|
||||
|
||||
<h2>Rezultati:</h2>
|
||||
<pre id="results"></pre>
|
||||
|
||||
<script>
|
||||
const webhookUrl = 'https://n8n.spletnimojster.si/webhook/joze/chat';
|
||||
const resultsEl = document.getElementById('results');
|
||||
|
||||
function logToResults(message, type = '') {
|
||||
const span = document.createElement('span');
|
||||
if (type === 'success') {
|
||||
span.className = 'success';
|
||||
} else if (type === 'error') {
|
||||
span.className = 'error';
|
||||
}
|
||||
span.textContent = message;
|
||||
|
||||
resultsEl.appendChild(span);
|
||||
resultsEl.append('\n\n' + '-'.repeat(50) + '\n\n');
|
||||
resultsEl.scrollTop = resultsEl.scrollHeight;
|
||||
}
|
||||
|
||||
async function runTest(testName, url, options) {
|
||||
logToResults(`🏃 Zagon testa: ${testName}`);
|
||||
logToResults(`URL: ${url}`);
|
||||
logToResults(`Opcije: ${JSON.stringify(options, null, 2)}`);
|
||||
|
||||
try {
|
||||
const response = await fetch(url, options);
|
||||
let responseBody = '';
|
||||
|
||||
const responseToParse = response.clone();
|
||||
|
||||
try {
|
||||
const jsonData = await responseToParse.json();
|
||||
responseBody = JSON.stringify(jsonData, null, 2);
|
||||
} catch (e) {
|
||||
responseBody = await responseToParse.text();
|
||||
if (!responseBody) {
|
||||
responseBody = "[Prazno telo odgovora]";
|
||||
}
|
||||
}
|
||||
|
||||
let responseHeaders = '';
|
||||
for (const [key, value] of response.headers.entries()) {
|
||||
responseHeaders += `${key}: ${value}\n`;
|
||||
}
|
||||
|
||||
const resultType = response.ok ? 'success' : 'error';
|
||||
logToResults(
|
||||
`Status: ${response.status} ${response.statusText}
|
||||
Glave odgovora (Headers):
|
||||
${responseHeaders}
|
||||
Telo odgovora (Body):
|
||||
${responseBody}`, resultType
|
||||
);
|
||||
|
||||
} catch (error) {
|
||||
logToResults(
|
||||
`Napaka: ${error.toString()}
|
||||
|
||||
Možni vzroki:
|
||||
1. CORS napaka (preverite konzolo brskalnika za podrobnosti!).
|
||||
2. Mrežna napaka (napačen URL, strežnik ni dosegljiv).`, 'error'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// --- DEFINICIJE TESTOV S POPRAVLJENIM FORMATOM PODATKOV ---
|
||||
|
||||
// Test 1: POST z JSON v pravilnem formatu, ki ga pričakuje n8n Chat Trigger
|
||||
document.getElementById('test-post-json').addEventListener('click', () => {
|
||||
runTest(
|
||||
'POST z application/json (Pravilen format)',
|
||||
webhookUrl,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
chatInput: 'Živjo, to je popravljen JSON test!',
|
||||
action: 'sendMessage'
|
||||
})
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Test 2: Preprost GET za preverjanje osnovne povezave
|
||||
document.getElementById('test-get').addEventListener('click', () => {
|
||||
runTest(
|
||||
'GET',
|
||||
webhookUrl,
|
||||
{ method: 'GET' }
|
||||
);
|
||||
});
|
||||
|
||||
// Test 3: Pošiljanje kot klasičen spletni obrazec s pravilnimi imeni polj
|
||||
document.getElementById('test-post-form').addEventListener('click', () => {
|
||||
runTest(
|
||||
'POST z application/x-www-form-urlencoded (Pravilen format)',
|
||||
webhookUrl,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({
|
||||
chatInput: 'Živjo, to je popravljen form data test!',
|
||||
action: 'sendMessage'
|
||||
})
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Nastavitev imena izhodne datoteke
|
||||
OUTPUT_FILE="code_export.txt"
|
||||
|
||||
# Odstrani izhodno datoteko, če že obstaja, da začnemo s čisto datoteko
|
||||
if [ -f "$OUTPUT_FILE" ]; then
|
||||
rm "$OUTPUT_FILE"
|
||||
fi
|
||||
|
||||
# Poišči vse datoteke, razen skritih datotek in določenih map (npr. node_modules).
|
||||
# Dodane so izjeme za slike, videoposnetke, PDF-je, arhive in druge binarne datoteke
|
||||
# neposredno v ukaz 'find' za boljšo zmogljivost.
|
||||
find . -type f \
|
||||
-not -path "*/\.*" \
|
||||
-not -path "*node_modules*" \
|
||||
-not -path "*vendor*" \
|
||||
-not -path "*dist*" \
|
||||
-not -path "*build*" \
|
||||
-not -path "*/images/*" \
|
||||
-not -iname "*.jpg" -not -iname "*.jpeg" \
|
||||
-not -iname "*.png" -not -iname "*.gif" \
|
||||
-not -iname "*.bmp" -not -iname "*.tiff" \
|
||||
-not -iname "*.svg" -not -iname "*.ico" \
|
||||
-not -iname "*.webp" \
|
||||
-not -iname "*.mp4" -not -iname "*.mov" \
|
||||
-not -iname "*.avi" -not -iname "*.mkv" \
|
||||
-not -iname "*.webm" \
|
||||
-not -iname "*.mp3" -not -iname "*.wav" \
|
||||
-not -iname "*.ogg" -not -iname "*.flac" \
|
||||
-not -iname "*.pdf" \
|
||||
-not -iname "*.zip" \
|
||||
-not -iname "*.tar" \
|
||||
-not -iname "*.gz" \
|
||||
-not -iname "*.bz2" \
|
||||
-not -iname "*.rar" \
|
||||
-not -iname "*.7z" \
|
||||
-not -iname "*.doc" -not -iname "*.docx" \
|
||||
-not -iname "*.xls" -not -iname "*.xlsx" \
|
||||
-not -iname "*.ppt" -not -iname "*.pptx" \
|
||||
-not -iname "*.eot" -not -iname "*.ttf" \
|
||||
-not -iname "*.woff" -not -iname "*.woff2" \
|
||||
| sort | while read -r file; do
|
||||
|
||||
# Preskoči samo izhodno datoteko in to skripto
|
||||
if [[ "$file" == "./$OUTPUT_FILE" || "$file" == "./export_code.sh" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Dodatna varnostna preverba: preskoči slikovne datoteke po MIME tipu
|
||||
if file --mime-type -b "$file" | grep -qiE '^(image)/'; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Dodaj ime datoteke in njeno vsebino v izhodno datoteko
|
||||
echo "\"$file\" : " >> "$OUTPUT_FILE"
|
||||
echo "\"\"\"" >> "$OUTPUT_FILE"
|
||||
cat "$file" >> "$OUTPUT_FILE"
|
||||
echo "\"\"\"" >> "$OUTPUT_FILE"
|
||||
echo "" >> "$OUTPUT_FILE"
|
||||
echo "" >> "$OUTPUT_FILE"
|
||||
done
|
||||
|
||||
echo "Izvoz kode končan. Vsebina je shranjena v datoteko $OUTPUT_FILE"
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 586 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
|
|
@ -0,0 +1,397 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="sl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>AI Mojster - AI Chatboti in Avtomatizacija za Vaše Podjetje</title>
|
||||
<meta name="title" content="AI Mojster - AI Chatboti in Avtomatizacija za Vaše Podjetje">
|
||||
<meta name="description" content="Povečajte prodajo, znižajte stroške in zagotovite podporo 24/7 z naprednimi AI chatboti in avtomatizacijo poslovnih procesov po meri.">
|
||||
<meta name="keywords" content="ai chatbot, umetna inteligenca, avtomatizacija, izdelava chatbota, poslovna avtomatizacija, ai mojster, n8n, chatbot slovenija">
|
||||
<meta name="author" content="AI Mojster">
|
||||
<meta name="robots" content="index, follow">
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://aimojster.si/">
|
||||
<meta property="og:title" content="AI Mojster - AI Chatboti in Avtomatizacija za Vaše Podjetje">
|
||||
<meta property="og:description" content="Povečajte prodajo, znižajte stroške in zagotovite podporo 24/7 z naprednimi AI chatboti in avtomatizacijo poslovnih procesov po meri.">
|
||||
<meta property="og:image" content="https://aimojster.si/images/og-image-ai.jpg">
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image">
|
||||
<meta property="twitter:url" content="https://aimojster.si/">
|
||||
<meta property="twitter:title" content="AI Mojster - AI Chatboti in Avtomatizacija za Vaše Podjetje">
|
||||
<meta property="twitter:description" content="Povečajte prodajo, znižajte stroške in zagotovite podporo 24/7 z naprednimi AI chatboti in avtomatizacijo poslovnih procesov po meri.">
|
||||
<meta property="twitter:image" content="https://aimojster.si/images/og-image-ai.jpg">
|
||||
|
||||
<!-- Favicon & Manifest -->
|
||||
<link rel="icon" type="image/png" href="images/favicon.png">
|
||||
<link rel="manifest" href="site.webmanifest">
|
||||
<meta name="theme-color" content="#7B2DFF">
|
||||
|
||||
<!-- Google Analytics 4 -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NCHQR1VBE8"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-NCHQR1VBE8');
|
||||
</script>
|
||||
|
||||
<!-- Fonts & Styles -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<header class="header">
|
||||
<nav class="navbar">
|
||||
<div class="logo logo-header">
|
||||
<a href="#">
|
||||
<img src="images/logo.png" alt="AI Mojster Logo">
|
||||
</a>
|
||||
</div>
|
||||
<div class="menu-toggle">
|
||||
<i class="fas fa-bars"></i>
|
||||
</div>
|
||||
<div class="nav-links">
|
||||
<a href="#solutions">Rešitve</a>
|
||||
<a href="#packages">Paketi</a>
|
||||
<a href="#benefits">Prednosti</a>
|
||||
<a href="#process">Postopek</a>
|
||||
<a href="#about">O nas</a>
|
||||
<a href="#contact" class="cta-button">Kontakt</a>
|
||||
<a href="tel:040654730" class="phone-number"><i class="fas fa-phone"></i> 040 654 730</a>
|
||||
<a href="/en/" class="language-switch"><i class="fas fa-globe"></i> EN</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="hero">
|
||||
<h1>Preobrazite Svoje Poslovanje z Močjo Umetne Inteligence</h1>
|
||||
<p class="hero-text">Nudimo napredne AI chatbote in avtomatizacijo po meri, ki znižujejo stroške, povečujejo prodajo in zagotavljajo podporo 24/7.</p>
|
||||
<div class="hero-features">
|
||||
<div class="hero-feature">
|
||||
<i class="fas fa-headset"></i>
|
||||
<span>Podpora 24/7</span>
|
||||
</div>
|
||||
<div class="hero-feature">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
<span>Povečana Prodaja</span>
|
||||
</div>
|
||||
<div class="hero-feature">
|
||||
<i class="fas fa-cogs"></i>
|
||||
<span>Avtomatizacija Procesov</span>
|
||||
</div>
|
||||
<div class="hero-feature">
|
||||
<i class="fas fa-euro-sign"></i>
|
||||
<span>Znižanje Stroškov</span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="#packages" class="cta-button">Odkrijte Svojo AI Rešitev</a>
|
||||
</section>
|
||||
|
||||
<section id="solutions" class="about">
|
||||
<div class="container">
|
||||
<h2>Naše Rešitve za Vaš Uspeh</h2>
|
||||
<p class="section-subtitle">Specializirani smo za dve ključni področji, ki prinašata takojšnje in merljive rezultate za vaše podjetje.</p>
|
||||
<div class="about-content">
|
||||
<div class="about-text">
|
||||
<h3><i class="fas fa-comments"></i> AI Chatboti po Meri</h3>
|
||||
<p>Pozabite na generične odgovore. Razvijemo inteligentne chatbote, ki razumejo vaše stranke, odgovarjajo na njihova vprašanja v realnem času, zbirajo povpraševanja in jih vodijo skozi nakupni proces. Izboljšajte uporabniško izkušnjo in pretvorite obiskovalce v zveste stranke.</p>
|
||||
</div>
|
||||
<div class="about-text">
|
||||
<h3><i class="fas fa-robot"></i> AI Avtomatizacija Procesov</h3>
|
||||
<p>Osvobodite svojo ekipo ponavljajočih se nalog. Povežemo vaše aplikacije (CRM, e-pošta, socialna omrežja) v pametne delovne tokove, ki delujejo samodejno. Od avtomatiziranega pošiljanja ponudb do sinhronizacije podatkov – prihranite čas, zmanjšajte napake in se osredotočite na rast.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="packages" class="packages">
|
||||
<h2>Izberite Paket, ki Poganja Vašo Rast</h2>
|
||||
<p class="section-subtitle">Pregledne cene, brez skritih stroškov. Naložba v AI se vam bo večkratno povrnila.</p>
|
||||
<div class="billing-toggle">
|
||||
<span>Mesečni najem</span>
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="billing-toggle">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
<span>Letni najem <span class="yearly-discount">Prihranite do 20%</span></span>
|
||||
</div>
|
||||
<div class="package-grid">
|
||||
<div class="package-card" data-package="asistent">
|
||||
<h3>AI Asistent</h3>
|
||||
<p class="subtitle">Za podjetja, ki želijo avtomatizirati podporo in zbirati kontakte.</p>
|
||||
<div class="price-period">
|
||||
<div class="price">39 €<span>/mesec</span></div>
|
||||
<small class="vat-price">47,58 € z DDV</small>
|
||||
</div>
|
||||
<ul>
|
||||
<li>Chatbot z odgovori na pogosta vprašanja</li>
|
||||
<li>Zbiranje kontaktnih podatkov (leadov)</li>
|
||||
<li>Namestitev na vašo spletno stran</li>
|
||||
<li>Osnovno poročanje o pogovorih</li>
|
||||
<li>E-mail podpora</li>
|
||||
</ul>
|
||||
<a href="#contact" class="package-button">Izberi Asistenta</a>
|
||||
</div>
|
||||
|
||||
<div class="package-card featured" data-package="partner">
|
||||
<div class="popular-badge">Najbolj priljubljen</div>
|
||||
<h3>AI Strateški Partner</h3>
|
||||
<p class="subtitle">Za podjetja, ki želijo integracijo, personalizacijo in večjo prodajo.</p>
|
||||
<div class="price-period">
|
||||
<div class="price">89 €<span>/mesec</span></div>
|
||||
<small class="vat-price">108,58 € z DDV</small>
|
||||
</div>
|
||||
<ul>
|
||||
<li>Vse iz paketa AI Asistent</li>
|
||||
<li>Integracija s CRM sistemom</li>
|
||||
<li>Napredni pogovorni scenariji</li>
|
||||
<li>Kvalifikacija potencialnih strank</li>
|
||||
<li>Možnost večjezične podpore</li>
|
||||
<li>Telefonska podpora</li>
|
||||
</ul>
|
||||
<a href="#contact" class="package-button">Izberi Partnerja</a>
|
||||
</div>
|
||||
|
||||
<div class="package-card" data-package="avtomatizacija">
|
||||
<h3>AI Avtomatizacija</h3>
|
||||
<p class="subtitle">Za podjetja, ki želijo celovito avtomatizacijo internih in zunanjih procesov.</p>
|
||||
<div class="price-period">
|
||||
<div class="price">149 €<span>/mesec</span></div>
|
||||
<small class="vat-price">181,78 € z DDV</small>
|
||||
</div>
|
||||
<ul>
|
||||
<li>Vse iz paketa AI Partner</li>
|
||||
<li>Kompleksni avtomatizacijski tokovi (n8n)</li>
|
||||
<li>API integracije po meri</li>
|
||||
<li>Povezava z e-poštnimi orodji</li>
|
||||
<li>Avtomatizirano upravljanje s podatki</li>
|
||||
<li>Prioritetna tehnična podpora</li>
|
||||
</ul>
|
||||
<a href="#contact" class="package-button">Izberi Avtomatizacijo</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="benefits" class="why-us">
|
||||
<div class="container">
|
||||
<h2>Prednosti Umetne Inteligence za Vas</h2>
|
||||
<p class="section-subtitle">To niso le tehnične rešitve. To so konkretne koristi, ki jih bo vaše podjetje občutilo takoj.</p>
|
||||
<div class="benefits-grid">
|
||||
<div class="benefit-card">
|
||||
<div class="benefit-icon"><i class="fas fa-clock"></i></div>
|
||||
<h3>Neprekinjena Dosegljivost 24/7</h3>
|
||||
<p>Vaš AI asistent nikoli ne spi. Strankam je na voljo podnevi in ponoči, med vikendi in prazniki, kar zagotavlja takojšnjo podporo in večje zadovoljstvo.</p>
|
||||
</div>
|
||||
<div class="benefit-card">
|
||||
<div class="benefit-icon"><i class="fas fa-piggy-bank"></i></div>
|
||||
<h3>Takojšnji Prihranki</h3>
|
||||
<p>Zmanjšajte stroške za podporo strankam za do 30%. Avtomatizirajte odgovore na ponavljajoča se vprašanja in sprostite svojo ekipo za naloge, ki prinašajo večjo vrednost.</p>
|
||||
</div>
|
||||
<div class="benefit-card">
|
||||
<div class="benefit-icon"><i class="fas fa-rocket"></i></div>
|
||||
<h3>Povečana Prodaja in Leadi</h3>
|
||||
<p>AI chatbot aktivno nagovarja obiskovalce, jih kvalificira in zbira njihove podatke. Nikoli več ne zamudite priložnosti za posel, tudi ko niste na voljo.</p>
|
||||
</div>
|
||||
<div class="benefit-card">
|
||||
<div class="benefit-icon"><i class="fas fa-brain"></i></div>
|
||||
<h3>Inteligentno Zbiranje Podatkov</h3>
|
||||
<p>Spoznajte svoje stranke bolje kot kdajkoli prej. Chatbot zbira ključne informacije o njihovih željah in težavah, kar vam omogoča sprejemanje pametnejših poslovnih odločitev.</p>
|
||||
</div>
|
||||
<div class="benefit-card">
|
||||
<div class="benefit-icon"><i class="fas fa-tasks"></i></div>
|
||||
<h3>Nič Več Ponavljajočega Dela</h3>
|
||||
<p>Ročno prepisovanje podatkov, pošiljanje istih e-mailov in ostala dolgočasna opravila postanejo preteklost. Osredotočite se na tisto, kar je resnično pomembno – rast vašega posla.</p>
|
||||
</div>
|
||||
<div class="benefit-card">
|
||||
<div class="benefit-icon"><i class="fas fa-user-friends"></i></div>
|
||||
<h3>Izjemna Uporabniška Izkušnja</h3>
|
||||
<p>Stranke cenijo hitre in natančne odgovore. Z AI zagotovite dosledno in profesionalno komunikacijo, ki gradi zaupanje in lojalnost vaši blagovni znamki.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="process" class="process">
|
||||
<div class="container">
|
||||
<h2>Od Ideje do Rezultatov v 4 Korakih</h2>
|
||||
<p class="section-subtitle">Naš proces je preprost, pregleden in osredotočen na doseganje vaših ciljev.</p>
|
||||
<div class="process-steps">
|
||||
<div class="step">
|
||||
<div class="step-number">1</div>
|
||||
<h3>Posvet in Analiza</h3>
|
||||
<p>Skupaj definiramo vaše cilje in analiziramo procese, ki so zreli za avtomatizacijo.</p>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">2</div>
|
||||
<h3>Načrtovanje in Razvoj</h3>
|
||||
<p>Zasnovo chatbota ali avtomatizacije prilagodimo vašim specifičnim potrebam in blagovni znamki.</p>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">3</div>
|
||||
<h3>Implementacija in Testiranje</h3>
|
||||
<p>Rešitev integriramo v vaše okolje in jo temeljito stestiramo za brezhibno delovanje.</p>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step-number">4</div>
|
||||
<h3>Zagon in Optimizacija</h3>
|
||||
<p>Po zagonu spremljamo delovanje in ga nenehno izboljšujemo za doseganje maksimalnih rezultatov.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="about" class="about">
|
||||
<div class="container">
|
||||
<h2>Kdo Smo?</h2>
|
||||
<div class="about-content">
|
||||
<div class="about-text">
|
||||
<h3>Vaši Strokovnjaki za Umetno Inteligenco</h3>
|
||||
<p>Smo ekipa navdušencev nad tehnologijo, ki verjame, da umetna inteligenca ni več prihodnost, ampak sedanjost. Naše poslanstvo je, da napredne AI rešitve približamo podjetjem vseh velikosti in jim pomagamo postati učinkovitejši, bolj konkurenčni in uspešnejši.</p>
|
||||
|
||||
<h3>Zaupajo nam uspešni:</h3>
|
||||
<ul class="client-list">
|
||||
<li><strong><a href="https://4spaces.io" target="_blank">4spaces</a></strong> - Podjetje za pametne rešitve</li>
|
||||
<li><strong><a href="https://oblikovalnica.eu" target="_blank">Oblikovalnica</a></strong> - Kopirnica</li>
|
||||
<li><strong><a href="https://pc-pomlad.si" target="_blank">PC Pomlad</a></strong> - Psihoterapevtski center</li>
|
||||
<li><strong><a href="https://pekarnakovac.si" target="_blank">Pekarna Kovač</a></strong> - Pekarna in slaščičarna</li>
|
||||
</ul>
|
||||
|
||||
<a href="#contact" class="about-cta">Naredimo korak naprej skupaj!</a>
|
||||
</div>
|
||||
<div class="about-features">
|
||||
<div class="about-feature">
|
||||
<i class="fas fa-lightbulb"></i>
|
||||
<h4>Strateško Načrtovanje</h4>
|
||||
<p>Ne prodajamo le tehnologije, ampak celovite rešitve, ki rešujejo vaše poslovne izzive.</p>
|
||||
</div>
|
||||
<div class="about-feature">
|
||||
<i class="fas fa-code"></i>
|
||||
<h4>Razvoj po Meri</h4>
|
||||
<p>Vsak chatbot in avtomatizacija sta 100% prilagojena vašemu poslu in ciljem.</p>
|
||||
</div>
|
||||
<div class="about-feature">
|
||||
<i class="fas fa-wrench"></i>
|
||||
<h4>Zanesljiva Podpora</h4>
|
||||
<p>Smo vaš dolgoročni partner. Nudimo redno vzdrževanje, optimizacijo in tehnično podporo.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="contact" class="contact">
|
||||
<h2>Pripravljeni na Prihodnost?</h2>
|
||||
<p class="contact-text">Naredite prvi korak k pametnejšemu poslovanju. Kontaktirajte nas za neobvezujoč pogovor in odkrijte, kako lahko AI pomaga tudi vam.</p>
|
||||
<p class="contact-options">Izpolnite obrazec ali nam pišite na <a href="mailto:info@aimojster.si">info@aimojster.si</a></p>
|
||||
<form id="contact-form" class="contact-form">
|
||||
<div class="form-group">
|
||||
<label for="name">Ime in priimek</label>
|
||||
<input type="text" id="name" name="name" required placeholder="Vnesite vaše ime in priimek">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">E-poštni naslov</label>
|
||||
<input type="email" id="email" name="email" required placeholder="Vnesite vaš e-poštni naslov">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="phone">Telefonska številka (neobvezno)</label>
|
||||
<input type="tel" id="phone" name="phone" placeholder="Vnesite vašo telefonsko številko">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="package">Zanima me paket</label>
|
||||
<select id="package" name="package" required>
|
||||
<option value="">Izberite paket...</option>
|
||||
<option value="asistent">AI Asistent - 39€/mesec</option>
|
||||
<option value="partner">AI Strateški Partner - 89€/mesec</option>
|
||||
<option value="avtomatizacija">AI Avtomatizacija - 149€/mesec</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="message">Vaše sporočilo</label>
|
||||
<textarea id="message" name="message" required placeholder="Na kratko opišite vaše potrebe in cilje..."></textarea>
|
||||
</div>
|
||||
<button type="submit" class="submit-button">
|
||||
Pošlji Povpraševanje
|
||||
</button>
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="footer-content">
|
||||
<div class="footer-logo">
|
||||
<a href="#">
|
||||
<img src="images/logo-white.png" alt="AI Mojster Logo">
|
||||
</a>
|
||||
<p>Inteligentne rešitve za pametno poslovanje.</p>
|
||||
</div>
|
||||
<div class="footer-links">
|
||||
<h4>Navigacija</h4>
|
||||
<a href="#solutions">Rešitve</a>
|
||||
<a href="#packages">Paketi</a>
|
||||
<a href="#benefits">Prednosti</a>
|
||||
<a href="#about">O nas</a>
|
||||
<a href="#contact">Kontakt</a>
|
||||
</div>
|
||||
<div class="footer-contact-info">
|
||||
<h4>Kontakt</h4>
|
||||
<p class="company-name">LEO MEDIA d.o.o.</p>
|
||||
<p class="address">Župančičeva ulica 3C<br>1233 Dob, Slovenia</p>
|
||||
<div class="contact-methods">
|
||||
<a href="tel:040654730"><i class="fas fa-phone"></i> 040 654 730</a>
|
||||
<a href="mailto:info@aimojster.si"><i class="fas fa-envelope"></i> info@aimojster.si</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<div class="legal-links">
|
||||
<a href="privacy.html">Pravilnik o zasebnosti</a>
|
||||
<a href="terms.html">Pogoji uporabe</a>
|
||||
</div>
|
||||
<p>© 2025 LEO Media d.o.o. - Vse pravice pridržane</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Chatbot Widget HTML -->
|
||||
<div id="chat-widget-container" class="hidden">
|
||||
<div class="chat-header">
|
||||
<h3>AI Asistent</h3>
|
||||
<button id="close-chat-btn">×</button>
|
||||
</div>
|
||||
<div id="chat-messages"></div>
|
||||
<form id="chat-input-form">
|
||||
<input type="text" id="chat-input" placeholder="Vpišite sporočilo..." autocomplete="off">
|
||||
<button type="submit" aria-label="Pošlji sporočilo"><i class="fas fa-paper-plane"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
<button id="chat-widget-button" aria-label="Odpri klepet">
|
||||
<i class="fas fa-robot"></i>
|
||||
</button>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="script.js"></script>
|
||||
<script src="chatbot.js?version=20250916"></script>
|
||||
<script>
|
||||
// Register Service Worker
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', () => {
|
||||
navigator.serviceWorker.register('/sw.js')
|
||||
.then(registration => {
|
||||
console.log('ServiceWorker registration successful');
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('ServiceWorker registration failed: ', err);
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
GENERAL JAVASCRIPT FOR AIMOJSTER.SI
|
||||
Last Updated: 16. September 2025
|
||||
Author: Gemini AI for AIMojster.si
|
||||
|
||||
This script handles general functionalities for the website, including:
|
||||
- Mobile navigation menu.
|
||||
- Smooth scrolling for anchor links.
|
||||
- Billing toggle (monthly/yearly) for pricing packages.
|
||||
- Contact form submission.
|
||||
- Intersection Observer for animations.
|
||||
*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
//======================================================================
|
||||
// 1. MOBILNI MENI (NAVIGATION)
|
||||
//======================================================================
|
||||
const menuToggle = document.querySelector('.menu-toggle');
|
||||
const navLinks = document.querySelector('.nav-links');
|
||||
|
||||
if (menuToggle && navLinks) {
|
||||
menuToggle.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
navLinks.classList.toggle('active');
|
||||
const icon = menuToggle.querySelector('i');
|
||||
if (icon) {
|
||||
icon.classList.toggle('fa-bars');
|
||||
icon.classList.toggle('fa-times');
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('click', function(e) {
|
||||
const isClickInsideNav = navLinks.contains(e.target);
|
||||
const isClickOnToggle = menuToggle.contains(e.target);
|
||||
if (!isClickInsideNav && !isClickOnToggle && navLinks.classList.contains('active')) {
|
||||
navLinks.classList.remove('active');
|
||||
const icon = menuToggle.querySelector('i');
|
||||
if (icon) {
|
||||
icon.classList.remove('fa-times');
|
||||
icon.classList.add('fa-bars');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
navLinks.querySelectorAll('a').forEach(link => {
|
||||
link.addEventListener('click', () => {
|
||||
if (navLinks.classList.contains('active')) {
|
||||
navLinks.classList.remove('active');
|
||||
const icon = menuToggle.querySelector('i');
|
||||
if (icon) {
|
||||
icon.classList.remove('fa-times');
|
||||
icon.classList.add('fa-bars');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// 2. GLADKO DRSENJE (SMOOTH SCROLLING)
|
||||
//======================================================================
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
const targetId = this.getAttribute('href');
|
||||
const targetElement = document.querySelector(targetId);
|
||||
|
||||
if (targetElement) {
|
||||
targetElement.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//======================================================================
|
||||
// 3. PREKLOP MED MESEČNIM IN LETNIM NAJEMOM (BILLING TOGGLE)
|
||||
//======================================================================
|
||||
const billingToggle = document.getElementById('billing-toggle');
|
||||
if (billingToggle) {
|
||||
const packagePrices = {
|
||||
'asistent': { monthly: 39, yearly: 29 },
|
||||
'partner': { monthly: 89, yearly: 69 },
|
||||
'avtomatizacija': { monthly: 149, yearly: 119 }
|
||||
};
|
||||
|
||||
const updatePrices = (isYearly) => {
|
||||
document.querySelectorAll('.package-card').forEach(card => {
|
||||
const packageName = card.dataset.package;
|
||||
if (!packageName || !packagePrices[packageName]) return;
|
||||
|
||||
const priceValue = isYearly ? packagePrices[packageName].yearly : packagePrices[packageName].monthly;
|
||||
const priceWithVat = (priceValue * 1.22).toFixed(2).replace('.', ',');
|
||||
|
||||
const priceElement = card.querySelector('.price');
|
||||
const vatElement = card.querySelector('.vat-price');
|
||||
|
||||
if (priceElement) {
|
||||
priceElement.innerHTML = `${priceValue} €<span>/mesec</span>`;
|
||||
}
|
||||
if (vatElement) {
|
||||
vatElement.textContent = `${priceWithVat} € z DDV`;
|
||||
}
|
||||
});
|
||||
updateContactFormPackageOptions(isYearly);
|
||||
};
|
||||
|
||||
const updateContactFormPackageOptions = (isYearly) => {
|
||||
const packageSelect = document.getElementById('package');
|
||||
if (!packageSelect) return;
|
||||
|
||||
Array.from(packageSelect.options).forEach(option => {
|
||||
const packageName = option.value;
|
||||
if (packageName && packagePrices[packageName]) {
|
||||
const price = isYearly ? packagePrices[packageName].yearly : packagePrices[packageName].monthly;
|
||||
const packageTitle = option.text.split(' - ')[0];
|
||||
option.text = `${packageTitle} - ${price}€/mesec`;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
updatePrices(billingToggle.checked);
|
||||
billingToggle.addEventListener('change', (e) => {
|
||||
updatePrices(e.target.checked);
|
||||
});
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// 4. IZBIRA PAKETA IN POSODOBITEV KONTAKTNEGA OBRAZCA
|
||||
//======================================================================
|
||||
document.querySelectorAll('.package-button').forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const packageCard = this.closest('.package-card');
|
||||
if (packageCard) {
|
||||
const selectedPackage = packageCard.dataset.package;
|
||||
const contactFormPackageSelect = document.getElementById('package');
|
||||
if (contactFormPackageSelect) {
|
||||
contactFormPackageSelect.value = selectedPackage;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//======================================================================
|
||||
// 5. POŠILJANJE KONTAKTNEGA OBRAZCA (FORM SUBMISSION)
|
||||
//======================================================================
|
||||
const contactForm = document.getElementById('contact-form');
|
||||
if (contactForm) {
|
||||
contactForm.addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
const name = document.getElementById('name').value.trim();
|
||||
const email = document.getElementById('email').value.trim();
|
||||
const message = document.getElementById('message').value.trim();
|
||||
const selectedPackage = document.getElementById('package').value;
|
||||
const submitButton = this.querySelector('.submit-button');
|
||||
|
||||
if (!name || !email || !message || !selectedPackage) {
|
||||
alert('Prosimo, izpolnite vsa obvezna polja.');
|
||||
return;
|
||||
}
|
||||
|
||||
const originalButtonText = submitButton.textContent;
|
||||
submitButton.textContent = 'Pošiljanje...';
|
||||
submitButton.disabled = true;
|
||||
|
||||
const formData = {
|
||||
name: name,
|
||||
email: email,
|
||||
phone: document.getElementById('phone').value.trim(),
|
||||
package: selectedPackage,
|
||||
message: message
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch('send_email.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(formData)
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Težava z omrežno povezavo.');
|
||||
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
alert('Hvala za vaše sporočilo! Odgovorili vam bomo v najkrajšem možnem času.');
|
||||
contactForm.reset();
|
||||
} else {
|
||||
throw new Error(result.error || 'Prišlo je do napake pri pošiljanju sporočila.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
alert('Napaka: ' + error.message);
|
||||
} finally {
|
||||
submitButton.textContent = originalButtonText;
|
||||
submitButton.disabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// 6. ANIMACIJE OB DRSENJU (INTERSECTION OBSERVER)
|
||||
//======================================================================
|
||||
const animatedElements = document.querySelectorAll('.fade-in');
|
||||
if ('IntersectionObserver' in window) {
|
||||
const observer = new IntersectionObserver((entries, observer) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('visible');
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.1 });
|
||||
animatedElements.forEach(el => observer.observe(el));
|
||||
} else {
|
||||
animatedElements.forEach(el => el.classList.add('visible'));
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
/**
|
||||
* SEND_EMAIL.PHP - Skripta za obdelavo in pošiljanje kontaktnega obrazca za AIMojster.si
|
||||
* Last Updated: 16. September 2025
|
||||
* Author: Gemini AI for AIMojster.si
|
||||
*
|
||||
* Ta skripta sprejme podatke v JSON formatu, jih validira, sanitizira
|
||||
* in pošlje kot formatirano e-poštno sporočilo na določen naslov.
|
||||
* Vrne JSON odgovor o uspešnosti operacije.
|
||||
*/
|
||||
|
||||
//======================================================================
|
||||
// 1. ZAČETNE NASTAVITVE IN VARNOST
|
||||
//======================================================================
|
||||
|
||||
// Nastavimo glavo (header), da bo odgovor vedno v JSON formatu.
|
||||
// To je ključno za pravilno delovanje na strani odjemalca (JavaScript).
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
// Varnostna preverba: Dovolimo samo metodo POST.
|
||||
// S tem preprečimo, da bi kdo skripto klical neposredno preko brskalnika (z GET metodo).
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
// Pošljemo HTTP status 405 Method Not Allowed in sporočilo o napaki.
|
||||
http_response_code(405);
|
||||
echo json_encode(['success' => false, 'error' => 'Napačna metoda zahteve. Dovoljena je samo metoda POST.']);
|
||||
exit; // Takoj prekinemo izvajanje skripte.
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// 2. SPREJEM IN DEKODIRANJE PODATKOV
|
||||
//======================================================================
|
||||
|
||||
// Preberemo необdelane podatke iz telesa zahteve (request body).
|
||||
// To je potrebno, ker JavaScript pošilja podatke kot JSON, ne kot klasičen form-data.
|
||||
$json_payload = file_get_contents('php://input');
|
||||
|
||||
// Dekodiramo JSON niz v PHP asociativno polje.
|
||||
// Drugi parameter `true` zagotovi, da dobimo polje namesto objekta.
|
||||
$data = json_decode($json_payload, true);
|
||||
|
||||
// Preverimo, ali je prišlo do napake pri dekodiranju JSON-a.
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
http_response_code(400); // Bad Request
|
||||
echo json_encode(['success' => false, 'error' => 'Neveljaven JSON format podatkov.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// 3. VALIDACIJA PREJETIH PODATKOV
|
||||
//======================================================================
|
||||
|
||||
// Definiramo obvezna polja.
|
||||
$required_fields = ['name', 'email', 'message', 'package'];
|
||||
$errors = [];
|
||||
|
||||
foreach ($required_fields as $field) {
|
||||
if (empty($data[$field])) {
|
||||
$errors[] = "Polje '{$field}' je obvezno.";
|
||||
}
|
||||
}
|
||||
|
||||
// Posebej preverimo veljavnost e-poštnega naslova.
|
||||
if (!empty($data['email']) && !filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$errors[] = "Vneseni e-poštni naslov ni v veljavni obliki.";
|
||||
}
|
||||
|
||||
// Če so se pojavile napake pri validaciji, jih vrnemo odjemalcu.
|
||||
if (!empty($errors)) {
|
||||
http_response_code(400); // Bad Request
|
||||
echo json_encode(['success' => false, 'error' => implode(' ', $errors)]);
|
||||
exit;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// 4. SANITIZACIJA PODATKOV IN PRIPRAVA SPREMENLJIVK
|
||||
//======================================================================
|
||||
|
||||
// Sanitiziramo vse prejete podatke, da preprečimo XSS napade in druge zlorabe.
|
||||
// Uporabimo htmlspecialchars za kodiranje posebnih znakov in trim za odstranitev presledkov.
|
||||
$name = htmlspecialchars(trim($data['name']));
|
||||
$email = filter_var(trim($data['email']), FILTER_SANITIZE_EMAIL);
|
||||
$phone = isset($data['phone']) ? htmlspecialchars(trim($data['phone'])) : 'Ni vneseno';
|
||||
$package = htmlspecialchars(trim($data['package']));
|
||||
$message = htmlspecialchars(trim($data['message']));
|
||||
|
||||
|
||||
//======================================================================
|
||||
// 5. SESTAVLJANJE IN POŠILJANJE E-POŠTNEGA SPOROČILA
|
||||
//======================================================================
|
||||
|
||||
// --- Nastavitve E-pošte ---
|
||||
$to_email = 'info@aimojster.si'; // **POMEMBNO: Vnesite vaš pravi e-poštni naslov!**
|
||||
$subject = 'Novo povpraševanje s spletne strani AIMojster.si';
|
||||
|
||||
// --- Telo sporočila (Email Body) ---
|
||||
// Uporabimo jasne oznake za preglednost.
|
||||
$email_body = "Prejeli ste novo povpraševanje preko kontaktnega obrazca na spletni strani AIMojster.si.\n\n";
|
||||
$email_body .= "--------------------------------------------------\n";
|
||||
$email_body .= "Ime in priimek: " . $name . "\n";
|
||||
$email_body .= "E-poštni naslov: " . $email . "\n";
|
||||
$email_body .= "Telefonska številka: " . $phone . "\n";
|
||||
$email_body .= "Izbrani paket: " . $package . "\n\n";
|
||||
$email_body .= "Sporočilo:\n" . $message . "\n";
|
||||
$email_body .= "--------------------------------------------------\n";
|
||||
$email_body .= "To sporočilo je bilo poslano samodejno.";
|
||||
|
||||
// --- Glave sporočila (Email Headers) ---
|
||||
// Pravilno nastavljene glave so ključne za zanesljivo dostavo in preprečevanje, da bi sporočilo končalo v vsiljeni pošti.
|
||||
$headers = "From: no-reply@aimojster.si\r\n"; // Uporabite naslov z vaše domene.
|
||||
$headers .= "Reply-To: " . $email . "\r\n"; // To vam omogoča, da direktno odgovorite pošiljatelju.
|
||||
$headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
|
||||
$headers .= "X-Mailer: PHP/" . phpversion();
|
||||
|
||||
// --- Pošiljanje ---
|
||||
// Uporabimo PHP funkcijo mail(). Če je pošiljanje uspešno, vrne true.
|
||||
if (mail($to_email, $subject, $email_body, $headers)) {
|
||||
// Pošiljanje je uspelo, vrnemo pozitiven odgovor.
|
||||
echo json_encode(['success' => true]);
|
||||
} else {
|
||||
// Pošiljanje ni uspelo. Vrnemo napako.
|
||||
http_response_code(500); // Internal Server Error
|
||||
echo json_encode(['success' => false, 'error' => 'Napaka strežnika pri pošiljanju sporočila. Prosimo, poskusite kasneje.']);
|
||||
}
|
||||
|
||||
exit; // Zaključimo izvajanje skripte.
|
||||
|
||||
?>
|
||||
Loading…
Reference in New Issue