%
-AI Contribution
-%
-Human Contribution
-| Timestamp | -Task | -Project | -Output Type | -Duration | -
|---|---|---|---|---|
| - | - | - | - - - - | -- |
| No activity logged yet. | -||||
Past timesheets will be shown here.
-diff --git a/api/leads.php b/api/leads.php new file mode 100644 index 0000000..8d28f53 --- /dev/null +++ b/api/leads.php @@ -0,0 +1,31 @@ + false, 'error' => 'Invalid request method']); + exit; +} + +$name = trim($_POST['name'] ?? ''); +$email = trim($_POST['email'] ?? ''); +$message = trim($_POST['message'] ?? ''); + +if (empty($name) || empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) { + echo json_encode(['success' => false, 'error' => 'Please provide a valid name and email address.']); + exit; +} + +try { + $stmt = db()->prepare("INSERT INTO leads (name, email, message) VALUES (?, ?, ?)"); + $stmt->execute([$name, $email, $message]); + + // Optional: Send email notification + // MailService::sendContactMessage($name, $email, $message); + + echo json_encode(['success' => true, 'message' => 'Thank you! We will get back to you shortly.']); +} catch (Exception $e) { + error_log($e->getMessage()); + echo json_encode(['success' => false, 'error' => 'Something went wrong. Please try again later.']); +} diff --git a/assets/css/custom.css b/assets/css/custom.css index 0607e66..819ca71 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -1,118 +1,120 @@ -/* Inter font from Google Fonts */ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); +:root { + --primary-color: #8A2BE2; /* Electric Purple */ + --secondary-color: #1A1A1A; /* Deep Charcoal */ + --accent-color: #FF3E00; /* Vibrant Orange/Red */ + --bg-color: #0F0F0F; + --text-color: #FFFFFF; + --text-muted: #A0A0A0; + --card-bg: #1A1A1A; + --border-color: #333333; +} body { - font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; - background-color: #F8F9FA; - color: #212529; + background-color: var(--bg-color); + color: var(--text-color); + font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + line-height: 1.6; +} + +h1, h2, h3, h4, h5, h6 { + font-weight: 800; + letter-spacing: -0.02em; +} + +.text-primary { color: var(--primary-color) !important; } +.bg-primary { background-color: var(--primary-color) !important; } + +.btn-primary { + background-color: var(--primary-color); + border: none; + padding: 12px 24px; + font-weight: 600; + transition: all 0.3s ease; + border-radius: 4px; +} + +.btn-primary:hover { + background-color: #7A1BD2; + transform: translateY(-2px); + box-shadow: 0 4px 15px rgba(138, 43, 226, 0.4); +} + +.navbar { + background-color: rgba(15, 15, 15, 0.9) !important; + backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border-color); +} + +.hero-section { + padding: 120px 0; + background: radial-gradient(circle at 50% 50%, rgba(138, 43, 226, 0.1) 0%, rgba(15, 15, 15, 1) 70%); +} + +.section-padding { + padding: 100px 0; } .card { - border-radius: 0.25rem; - border: 1px solid #DEE2E6; + background-color: var(--card-bg); + border: 1px solid var(--border-color); + border-radius: 4px; + transition: all 0.3s ease; } -.table { - border: 1px solid #DEE2E6; +.card:hover { + border-color: var(--primary-color); } -.badge-ai { - background-color: #007BFF; +.service-card { + padding: 40px; + height: 100%; +} + +.service-icon { + font-size: 2.5rem; + margin-bottom: 20px; + color: var(--primary-color); +} + +.form-control { + background-color: #222; + border: 1px solid var(--border-color); + color: #fff; + padding: 12px; + border-radius: 4px; +} + +.form-control:focus { + background-color: #2a2a2a; + border-color: var(--primary-color); + color: #fff; + box-shadow: none; +} + +.footer { + border-top: 1px solid var(--border-color); + padding: 60px 0; + background-color: #0A0A0A; +} + +.badge-vibrant { + background-color: var(--accent-color); + color: white; + font-size: 0.8rem; + padding: 5px 12px; + border-radius: 20px; +} + +/* Toast styling */ +.toast-container { + position: fixed; + bottom: 20px; + right: 20px; + z-index: 1050; +} + +.toast { + background-color: var(--card-bg); + border: 1px solid var(--primary-color); color: white; } - -.badge-human { - background-color: #6C757D; - color: white; -} - -#chat-container { - height: 70vh; - display: flex; - flex-direction: column; -} - -#chat-box { - flex-grow: 1; - overflow-y: auto; - padding: 1rem; - display: flex; - flex-direction: column; - gap: 0.75rem; -} - -.message { - padding: 0.5rem 1rem; - border-radius: 1rem; - max-width: 80%; - word-wrap: break-word; -} - -.user-message { - background-color: #007BFF; - color: white; - align-self: flex-end; - border-bottom-right-radius: 0; -} - -.bot-message { - background-color: #E9ECEF; - color: #212529; - align-self: flex-start; - border-bottom-left-radius: 0; -} - -.bot-message.typing-indicator { - display: flex; - align-items: center; - gap: 5px; -} - -.dot-flashing { - position: relative; - width: 6px; - height: 6px; - border-radius: 5px; - background-color: #6C757D; - color: #6C757D; - animation: dotFlashing 1s infinite linear alternate; - animation-delay: .5s; -} - -.dot-flashing::before, .dot-flashing::after { - content: ''; - display: inline-block; - position: absolute; - top: 0; -} - -.dot-flashing::before { - left: -10px; - width: 6px; - height: 6px; - border-radius: 5px; - background-color: #6C757D; - color: #6C757D; - animation: dotFlashing 1s infinite alternate; - animation-delay: 0s; -} - -.dot-flashing::after { - left: 10px; - width: 6px; - height: 6px; - border-radius: 5px; - background-color: #6C757D; - color: #6C757D; - animation: dotFlashing 1s infinite alternate; - animation-delay: 1s; -} - -@keyframes dotFlashing { - 0% { - background-color: #6C757D; - } - 50%, 100% { - background-color: #E9ECEF; - } -} \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js index c180efc..cd01dfe 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,276 +1,66 @@ -document.addEventListener('DOMContentLoaded', () => { - const chatForm = document.getElementById('chat-form'); - const chatInput = document.getElementById('chat-input'); - const chatBox = document.getElementById('chat-box'); - const activityLogBody = document.getElementById('activity-log-body'); - const logCount = document.getElementById('log-count'); - const emptyLogRew = document.getElementById('empty-log-row'); - const manualLogForm = document.getElementById('manual-log-form'); - const clockElement = document.getElementById('clock'); - const pastTimesheetsTab = document.getElementById('past-timesheets-tab'); - const pastTimesheetsContainer = document.getElementById('past-timesheets'); +document.addEventListener('DOMContentLoaded', function() { + const contactForm = document.getElementById('contactForm'); + const toastContainer = document.getElementById('toast-container'); - function updateClock() { - if (clockElement) { - const now = new Date(); - const time = now.toLocaleTimeString(); - const month = String(now.getMonth() + 1).padStart(2, '0'); - const day = String(now.getDate()).padStart(2, '0'); - const year = now.getFullYear(); - const date = `${month}-${day}-${year}`; - clockElement.textContent = `${time} ${date}`; - } - } + if (contactForm) { + contactForm.addEventListener('submit', function(e) { + e.preventDefault(); + + const submitBtn = contactForm.querySelector('button[type="submit"]'); + const originalBtnText = submitBtn.innerHTML; + submitBtn.disabled = true; + submitBtn.innerHTML = ' Sending...'; - updateClock(); - setInterval(updateClock, 1000); + const formData = new FormData(contactForm); - if (pastTimesheetsTab) { - pastTimesheetsTab.addEventListener('shown.bs.tab', () => { - loadPastTimesheets(); + fetch('api/leads.php', { + method: 'POST', + body: formData + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + showToast(data.message, 'success'); + contactForm.reset(); + } else { + showToast(data.error || 'Something went wrong.', 'danger'); + } + }) + .catch(error => { + console.error('Error:', error); + showToast('An error occurred. Please try again.', 'danger'); + }) + .finally(() => { + submitBtn.disabled = false; + submitBtn.innerHTML = originalBtnText; + }); }); } - async function loadPastTimesheets() { - pastTimesheetsContainer.innerHTML = '
Failed to load past timesheets.
'; - return; - } - - const data = await response.json(); - - if (data.error) { - pastTimesheetsContainer.innerHTML = `${data.error}
`; - return; - } - - if (!data.past_timesheets || data.past_timesheets.length === 0) { - pastTimesheetsContainer.innerHTML = '| Timestamp | -Task | -Project | -Output | -Duration | -
|---|---|---|---|---|
| ${activity.timestamp} | -${escapeHTML(activity.task)} | -${escapeHTML(activity.project)} | -${escapeHTML(activity.output_type)} | -${escapeHTML(activity.duration)} | -
An error occurred while fetching data.
'; - } - } - - chatForm.addEventListener('submit', async (e) => { - e.preventDefault(); - const userMessage = chatInput.value.trim(); - if (!userMessage) return; - - appendMessage(userMessage, 'user'); - chatInput.value = ''; - showTypingIndicator(); - - try { - const response = await fetch('api/chat.php', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ message: userMessage }) - }); - - removeTypingIndicator(); - - if (!response.ok) { - const errorData = await response.json(); - const errorMsg = errorData.error || 'An unknown error occurred.'; - appendMessage(`Error: ${errorMsg}`, 'bot'); - return; - } - - const data = await response.json(); - - if (data.error) { - appendMessage(`Error: ${data.error}`, 'bot'); - return; - } - - appendMessage(data.reply, 'bot'); - - if (data.new_log_entry) { - updateActivityLog(data.new_log_entry); - } - - } catch (error) { - removeTypingIndicator(); - appendMessage('Could not connect to the server. Please try again later.', 'bot'); - console.error("Fetch Error:", error); - } - }); - - manualLogForm.addEventListener('submit', async (e) => { - e.preventDefault(); - const actionType = document.getElementById('action-type').value; - const project = document.getElementById('manual-project').value.trim(); - const task = document.getElementById('manual-task').value.trim(); - - if (!project || !task) { - // You might want to show an error to the user - return; - } - - const payload = { - action: 'manual_log', - type: actionType, - project: project, - task: task - }; - - try { - const response = await fetch('api/chat.php', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(payload) - }); - - if (!response.ok) { - console.error('Manual log submission failed'); - return; - } - - const data = await response.json(); - - if (data.new_log_entry) { - updateActivityLog(data.new_log_entry); - manualLogForm.reset(); - } - } catch (error) { - console.error("Fetch Error:", error); - } - }); - - function appendMessage(message, sender) { - const messageElement = document.createElement('div'); - messageElement.classList.add('message', `${sender}-message`); - messageElement.textContent = message; - chatBox.appendChild(messageElement); - chatBox.scrollTop = chatBox.scrollHeight; - } - - function showTypingIndicator() { - const typingIndicator = document.createElement('div'); - typingIndicator.classList.add('message', 'bot-message', 'typing-indicator'); - typingIndicator.innerHTML = ''; - typingIndicator.id = 'typing-indicator'; - chatBox.appendChild(typingIndicator); - chatBox.scrollTop = chatBox.scrollHeight; - } - - function removeTypingIndicator() { - const typingIndicator = document.getElementById('typing-indicator'); - if (typingIndicator) { - typingIndicator.remove(); - } - } - - function updateActivityLog(logEntry) { - if(emptyLogRew) { - emptyLogRew.remove(); - } - - const newRow = document.createElement('tr'); - const badgeClass = logEntry.output_type === 'AI' ? 'badge-ai' : 'badge-human'; - newRow.innerHTML = ` -AI Contribution
-Human Contribution
-| Timestamp | -Task | -Project | -Output Type | -Duration | -
|---|---|---|---|---|
| - | - | - | - - - - | -- |
| No activity logged yet. | -||||
Past timesheets will be shown here.
-Tailored strategies to dominate every platform.
+High-converting viral content designed to capture attention and drive engagement across TikTok, Reels, and YouTube.
+Data-driven Meta and TikTok ad campaigns focused on ROI and scalable customer acquisition for your business.
+Building loyal fanbases and handling 24/7 engagement to turn followers into lifelong brand advocates.
+We don't just post; we perform. Our clients see an average of 300% growth in organic reach within the first 90 days.
+No hidden fees. Just growth.
+Perfect for startups.
+For established brands.
+Fill out the form below and our strategy team will be in touch within 24 hours.
+