backup and fixes

This commit is contained in:
2026-01-30 10:48:56 +01:00
parent cc4bfa5dbe
commit afcbd07d56
75 changed files with 6774 additions and 668 deletions

View File

@@ -1,11 +1,8 @@
<?php
/**
* Profice Web API Handler
* Centralized API endpoint for all form submissions, webhooks, and tracking
* ALL SENSITIVE DATA IS STORED HERE - NOT VISIBLE TO CLIENT
*
* @author Profice Development Team
* @version 2.0.0
* Profice Web API Handler - Centralized Configuration
* ALL SENSITIVE DATA STORED HERE - NOT VISIBLE TO CLIENT
* Handles webhooks, API, tokens, cookie consent, tracking
*/
// ==========================================
@@ -47,8 +44,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
// ==========================================
// Environment
define('USE_PRODUCTION', true);
define('DEBUG_MODE', false);
define('USE_PRODUCTION', false); // Use test webhook for debugging
define('DEBUG_MODE', true); // Enable debug to see errors
// N8N Webhooks
define('WEBHOOK_TEST', 'https://n8n.profice.de/webhook-test/d94ef798-3f43-46dd-8207-1e335e64518f');
@@ -186,7 +183,6 @@ function sendToWebhook($data, $webhookUrl = null) {
$url = $webhookUrl ?? WEBHOOK_URL;
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
@@ -197,24 +193,25 @@ function sendToWebhook($data, $webhookUrl = null) {
'User-Agent: Profice-Web-API/2.0'
],
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYPEER => !DEBUG_MODE, // Disable for debugging
CURLOPT_FOLLOWLOCATION => true
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
error_log("Webhook Error: " . $error);
return ['success' => false, 'error' => $error];
return ['success' => false, 'error' => $error, 'response' => $response];
}
return [
'success' => $httpCode >= 200 && $httpCode < 300,
'http_code' => $httpCode
'http_code' => $httpCode,
'response' => $response,
'error' => $error
];
}
@@ -251,96 +248,130 @@ function loadTrackingScripts($preferences) {
// Google Tag Manager
if ($preferences['analytics'] && !empty(GTM_CONTAINER_ID) && GTM_CONTAINER_ID !== 'GTM-XXXXXXX') {
$scripts['gtm'] = [
'type' => 'analytics',
'id' => GTM_CONTAINER_ID
'type' => 'gtm',
'src' => 'https://www.googletagmanager.com/gtm.js?id=' . GTM_CONTAINER_ID,
'config' => [
'id' => GTM_CONTAINER_ID
]
];
}
// Facebook Pixel
if ($preferences['marketing'] && !empty(FB_PIXEL_ID)) {
$scripts['fb'] = [
'type' => 'marketing',
'id' => FB_PIXEL_ID
'type' => 'pixel',
'src' => 'https://connect.facebook.net/en_US/fbevents.js',
'config' => [
'pixel_id' => FB_PIXEL_ID
]
];
}
// Google Ads
if ($preferences['marketing'] && !empty(GADS_CONVERSION_ID) && GADS_CONVERSION_ID !== 'AW-XXXXXXXXXX') {
$scripts['gads'] = [
'type' => 'marketing',
'id' => GADS_CONVERSION_ID
'type' => 'conversion',
'src' => 'https://www.googletagmanager.com/gtag/js?id=' . GADS_CONVERSION_ID,
'config' => [
'conversion_id' => GADS_CONVERSION_ID,
'conversion_label' => GADS_CONVERSION_LABEL
]
];
}
// LinkedIn
if ($preferences['marketing'] && !empty(LINKEDIN_PARTNER_ID)) {
$scripts['linkedin'] = [
'type' => 'marketing',
'id' => LINKEDIN_PARTNER_ID
'type' => 'insight',
'src' => 'https://snap.licdn.com/li.lms-analytics/insight.min.js',
'config' => [
'partner_id' => LINKEDIN_PARTNER_ID
]
];
}
return $scripts;
}
function trackEvent($eventName, $eventData, $preferences) {
$results = [];
// Server-side Google Analytics tracking
if ($preferences['analytics'] && !empty(GA_MEASUREMENT_ID) && !empty(GA_API_SECRET)) {
$results['ga'] = sendGAEvent($eventName, $eventData);
function sendEventToGA($data) {
if (empty(GA_MEASUREMENT_ID) || GA_MEASUREMENT_ID === 'G-XXXXXXXXXX') {
return false;
}
// Server-side Facebook Conversions API
if ($preferences['marketing'] && !empty(FB_PIXEL_ID) && !empty(FB_ACCESS_TOKEN)) {
$results['fb'] = sendFBEvent($eventName, $eventData);
$postData = [
'client_id' => $data['client_id'] ?? uniqid(),
'user_id' => $data['user_id'] ?? null,
'events' => [
[
'name' => $data['event_name'],
'params' => $data['params'] ?? []
]
]
];
$url = 'https://www.google-analytics.com/mp/collect';
$url .= '?measurement_id=' . GA_MEASUREMENT_ID;
$url .= '&api_secret=' . GA_API_SECRET;
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($postData),
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_TIMEOUT => 10
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpCode >= 200 && $httpCode < 300;
}
function sendEventToFB($data) {
if (empty(FB_PIXEL_ID) || empty(FB_ACCESS_TOKEN)) {
return false;
}
return $results;
}
function sendGAEvent($eventName, $eventData) {
if (empty(GA_API_SECRET)) return ['success' => false, 'error' => 'No API secret'];
$url = 'https://www.google-analytics.com/mp/collect?measurement_id=' . GA_MEASUREMENT_ID . '&api_secret=' . GA_API_SECRET;
$payload = [
'client_id' => $eventData['client_id'] ?? uniqid(),
'events' => [[
'name' => $eventName,
'params' => $eventData
]]
$postData = [
'data' => [
[
'event_name' => $data['event_name'],
'event_time' => time(),
'action_source' => 'website',
'user_data' => $data['user_data'] ?? [],
'custom_data' => $data['custom_data'] ?? []
]
]
];
return sendToWebhook($payload, $url);
}
function sendFBEvent($eventName, $eventData) {
if (empty(FB_ACCESS_TOKEN)) return ['success' => false, 'error' => 'No access token'];
$url = 'https://graph.facebook.com/v18.0/' . FB_PIXEL_ID . '/events';
$url .= '?access_token=' . FB_ACCESS_TOKEN;
$url = 'https://graph.facebook.com/v18.0/' . FB_PIXEL_ID . '/events?access_token=' . FB_ACCESS_TOKEN;
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($postData),
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_TIMEOUT => 10
]);
$payload = [
'data' => [[
'event_name' => $eventName,
'event_time' => time(),
'action_source' => 'website',
'user_data' => [
'client_ip_address' => getClientIP(),
'client_user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? ''
],
'custom_data' => $eventData
]]
];
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return sendToWebhook($payload, $url);
return $httpCode >= 200 && $httpCode < 300;
}
// ==========================================
// STORAGE FUNCTIONS
// ==========================================
function storeLead($formData) {
function storeLead($data) {
$leadFile = __DIR__ . '/data/leads.json';
$dir = dirname($leadFile);
@@ -354,16 +385,17 @@ function storeLead($formData) {
}
$lead = [
'id' => uniqid('lead_'),
'id' => uniqid('lead_', true),
'datum' => date('d.m.Y'),
'dienstleistung' => $formData['service'] ?? 'Allgemein',
'dienstleistung' => $data['service'] ?? 'Allgemein',
'status' => 'open',
'statusText' => 'Offen',
'description' => $formData['description'] ?? '',
'name' => $formData['name'] ?? '',
'contact' => $formData['contact'] ?? '',
'organisation' => $formData['organisation'] ?? '',
'timestamp' => date('c')
'description' => $data['description'] ?? '',
'name' => $data['name'] ?? '',
'contact' => $data['contact'] ?? '',
'organisation' => $data['organisation'] ?? '',
'timestamp' => date('c'),
'ip_address' => getClientIP()
];
array_unshift($leads, $lead);
@@ -373,8 +405,8 @@ function storeLead($formData) {
return $lead['id'];
}
function storeCookieConsent($consentData) {
$consentFile = __DIR__ . '/data/cookie_consents.json';
function storeCookieConsent($data) {
$consentFile = __DIR__ . '/data/cookie_consent.json';
$dir = dirname($consentFile);
if (!is_dir($dir)) {
@@ -386,39 +418,30 @@ function storeCookieConsent($consentData) {
$consents = json_decode(file_get_contents($consentFile), true) ?: [];
}
// Remove existing consent for this IP
$ip = getClientIP();
$consents = array_filter($consents, function($c) use ($ip) {
return ($c['ip_address'] ?? '') !== $ip;
});
$consent = [
'id' => uniqid('consent_', true),
'timestamp' => date('c'),
'preferences' => $data['preferences'] ?? [],
'ip_address' => getClientIP(),
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? ''
];
$consentData['id'] = uniqid('consent_');
$consentData['ip_address'] = $ip;
$consentData['timestamp'] = date('c');
array_unshift($consents, $consentData);
array_unshift($consents, $consent);
$consents = array_slice($consents, 0, 1000);
file_put_contents($consentFile, json_encode($consents, JSON_PRETTY_PRINT));
return $consent['id'];
}
function getCookieConsentByIP() {
$consentFile = __DIR__ . '/data/cookie_consents.json';
function getCookieConsent() {
$consentFile = __DIR__ . '/data/cookie_consent.json';
if (!file_exists($consentFile)) {
return null;
}
$consents = json_decode(file_get_contents($consentFile), true) ?: [];
$ip = getClientIP();
foreach ($consents as $consent) {
if (($consent['ip_address'] ?? '') === $ip) {
return $consent;
}
}
return null;
return $consents[0] ?? null;
}
// ==========================================
@@ -442,16 +465,31 @@ function handleContactForm($data) {
'description' => sanitizeInput($data['description'] ?? ''),
'timestamp' => date('c'),
'source' => 'contact_form',
'form_type' => 'offer',
'ip_address' => getClientIP()
];
// Store lead locally first
$leadId = storeLead($formData);
// Send to webhook
$webhookResult = sendToWebhook($formData);
// Always return success to user, but include webhook info in debug mode
$debugData = DEBUG_MODE ? [
'lead_id' => $leadId,
'webhook_result' => $webhookResult,
'webhook_url' => WEBHOOK_URL,
'form_data' => $formData
] : null;
if ($webhookResult['success']) {
storeLead($formData);
sendResponse(true, 'Formular erfolgreich gesendet', $debugData);
} else {
// Still return success to user but log the webhook error
error_log('Webhook failed but form was stored locally: ' . json_encode($webhookResult));
sendResponse(true, 'Formular erfolgreich gesendet (Webhook-Fehler protokolliert)', $debugData);
}
sendResponse(true, 'Formular erfolgreich gesendet');
}
function handleLoginForm($data) {
@@ -462,18 +500,8 @@ function handleLoginForm($data) {
}
}
$formData = [
'email' => sanitizeInput($data['email']),
'password' => $data['password'], // Don't sanitize password
'remember' => $data['remember'] ?? false,
'timestamp' => date('c'),
'source' => 'login_form',
'ip_address' => getClientIP()
];
$webhookResult = sendToWebhook($formData);
sendResponse(true, 'Anmeldung verarbeitet');
// Add your login logic here
sendResponse(true, 'Login erfolgreich');
}
function handleRegisterForm($data) {
@@ -484,80 +512,35 @@ function handleRegisterForm($data) {
}
}
$formData = [
'name' => sanitizeInput($data['name']),
'email' => sanitizeInput($data['email']),
'password' => $data['password'],
'company' => sanitizeInput($data['company'] ?? ''),
'phone' => sanitizeInput($data['phone'] ?? ''),
'timestamp' => date('c'),
'source' => 'register_form',
'ip_address' => getClientIP()
];
$webhookResult = sendToWebhook($formData);
// Add your registration logic here
sendResponse(true, 'Registrierung erfolgreich');
}
function handleLeadForm($data) {
$formData = [
'lead_data' => $data,
'timestamp' => date('c'),
'source' => 'lead_form',
'ip_address' => getClientIP()
];
$webhookResult = sendToWebhook($formData);
sendResponse(true, 'Lead erfolgreich gesendet');
// Handle lead form submissions
$leadId = storeLead($data);
sendResponse(true, 'Lead gespeichert', ['lead_id' => $leadId]);
}
function handleCookieConsent($data) {
if (empty($data['preferences'])) {
sendResponse(false, 'Preferences fehlen', null, 400);
}
$consentData = [
'hasConsented' => true,
'preferences' => $data['preferences'],
'source' => 'cookie_consent'
];
storeCookieConsent($consentData);
// Get tracking scripts based on consent
$scripts = loadTrackingScripts($data['preferences']);
// Send consent event to webhook
$webhookData = [
'event_type' => 'cookie_consent_update',
'preferences' => $data['preferences'],
'timestamp' => date('c'),
'ip_address' => getClientIP()
];
sendToWebhook($webhookData);
sendResponse(true, 'Cookie-Einstellungen gespeichert', ['scripts' => $scripts]);
$preferences = $data['preferences'] ?? [];
$consentId = storeCookieConsent(['preferences' => $preferences]);
// Load tracking scripts based on preferences
$scripts = loadTrackingScripts($preferences);
sendResponse(true, 'Cookie-Einstellungen gespeichert', [
'consent_id' => $consentId,
'scripts' => $scripts
]);
}
function handleGetCookieConsent($data) {
$consent = getCookieConsentByIP();
$consent = getCookieConsent();
if ($consent) {
// Get tracking scripts based on saved consent
$scripts = [];
if (!empty($consent['preferences'])) {
$scripts = loadTrackingScripts($consent['preferences']);
}
sendResponse(true, 'Consent gefunden', [
'hasConsented' => $consent['hasConsented'] ?? false,
'preferences' => $consent['preferences'] ?? [],
'scripts' => $scripts
]);
sendResponse(true, 'Cookie-Einstellungen gefunden', $consent);
} else {
sendResponse(false, 'Kein Consent gefunden', null, 404);
sendResponse(false, 'Keine Cookie-Einstellungen gefunden', null, 404);
}
}
@@ -567,14 +550,25 @@ function handleGetTrackingConfig($data) {
}
function handleTrackEvent($data) {
if (empty($data['event_name'])) {
sendResponse(false, 'Event name fehlt', null, 400);
}
$eventName = $data['event_name'] ?? '';
$eventData = $data['event_data'] ?? [];
$preferences = $data['preferences'] ?? ['analytics' => false, 'marketing' => false];
$results = trackEvent($data['event_name'], $data['event_data'] ?? [], $preferences);
// Send to Google Analytics
$gaSuccess = sendEventToGA([
'event_name' => $eventName,
'params' => $eventData
]);
sendResponse(true, 'Event getrackt', $results);
// Send to Facebook
$fbSuccess = sendEventToFB([
'event_name' => $eventName,
'custom_data' => $eventData
]);
sendResponse(true, 'Event gesendet', [
'ga_success' => $gaSuccess,
'fb_success' => $fbSuccess
]);
}
// ==========================================
@@ -637,6 +631,7 @@ try {
}
} catch (Exception $e) {
error_log('API Error: ' . $e->getMessage());
error_log('Stack trace: ' . $e->getTraceAsString());
sendResponse(false, 'Interner Serverfehler', null, 500);
}
?>
?>

View File

@@ -1,124 +0,0 @@
// details.js
document.addEventListener("DOMContentLoaded", function() {
const serviceDetails = {
'seo-optimierung': {
title: 'SEO Optimierung',
icon: '🔍',
description: 'Verbessern Sie Ihre Sichtbarkeit in Suchmaschinen und erreichen Sie mehr Kunden online.',
fullDescription: 'Unsere SEO-Optimierungsdienste helfen Ihnen, in Suchmaschinen besser gefunden zu werden. Wir analysieren Ihre Website, identifizieren Optimierungspotenziale und implementieren bewährte Strategien, um Ihr Ranking zu verbessern und mehr qualifizierte Besucher anzuziehen.',
features: [
'Keyword-Analyse und -Recherche',
'On-Page Optimierung',
'Technische SEO-Audits',
'Content-Strategie',
'Link-Building',
'Performance-Tracking'
],
benefits: [
'Höhere Sichtbarkeit in Suchmaschinen',
'Mehr qualifizierte Besucher',
'Verbesserte Conversion-Raten',
'Langfristiger ROI'
]
},
'cloud-migration': {
title: 'Cloud Migration',
icon: '☁️',
description: 'Modernisieren Sie Ihre IT-Infrastruktur mit sicheren und skalierbaren Cloud-Lösungen.',
fullDescription: 'Wir begleiten Sie bei der Migration Ihrer IT-Systeme in die Cloud. Von der Analyse Ihrer bestehenden Infrastruktur bis zur vollständigen Implementierung sorgen wir für einen reibungslosen Übergang mit minimalem Geschäftsausfall.',
features: [
'Infrastruktur-Analyse',
'Migrationsplanung',
'Datenübertragung',
'Sicherheit & Compliance',
'Performance-Optimierung',
'Schulung & Support'
],
benefits: [
'Kosteneinsparungen',
'Bessere Skalierbarkeit',
'Erhöhte Sicherheit',
'Flexiblere Arbeitsweise'
]
},
'datenanalyse': {
title: 'Datenanalyse',
icon: '📊',
description: 'Gewinnen Sie wertvolle Einblicke aus Ihren Daten mit unseren Analyse-Lösungen.',
fullDescription: 'Wir helfen Ihnen, Ihre Daten in wertvolle Erkenntnisse umzuwandeln. Mit modernen Analyse-Tools und -Methoden identifizieren wir Trends, Muster und Chancen, die Ihre Geschäftsentscheidungen verbessern.',
features: [
'Datenerfassung & -bereinigung',
'Statistische Analyse',
'Visualisierung & Dashboards',
'Predictive Analytics',
'Berichterstellung',
'Consulting'
],
benefits: [
'Bessere Entscheidungen',
'Prozessoptimierung',
'Kostensenkungen',
'Wettbewerbsvorteile'
]
}
};
const urlParams = new URLSearchParams(window.location.search);
const serviceId = urlParams.get('service');
const detailsContainer = document.getElementById('service-details');
if (serviceId && serviceDetails[serviceId]) {
const service = serviceDetails[serviceId];
detailsContainer.innerHTML = `
<div class="service-header">
<div class="service-icon-large">${service.icon}</div>
<h1 class="service-title-large">${service.title}</h1>
<p class="service-description-large">${service.description}</p>
</div>
<div class="service-content">
<section class="service-section">
<h2 class="section-title">Beschreibung</h2>
<p class="section-text">${service.fullDescription}</p>
</section>
<section class="service-section">
<h2 class="section-title">Unsere Leistungen</h2>
<ul class="feature-list">
${service.features.map(feature => `<li>${feature}</li>`).join('')}
</ul>
</section>
<section class="service-section">
<h2 class="section-title">Ihre Vorteile</h2>
<ul class="benefit-list">
${service.benefits.map(benefit => `<li>${benefit}</li>`).join('')}
</ul>
</section>
<section class="service-section">
<h2 class="section-title">Interesse?</h2>
<p class="section-text">Kontaktieren Sie uns für eine persönliche Beratung und ein maßgeschneidertes Angebot.</p>
<div class="cta-buttons">
<a href="offers.html" class="cta-btn primary">Kontakt aufnehmen</a>
<a href="leads.html" class="cta-btn secondary">Zurück zum Dashboard</a>
</div>
</section>
</div>
`;
// Update page title
document.title = `Profice - ${service.title}`;
} else {
// Fallback if no service specified
detailsContainer.innerHTML = `
<div class="error-message">
<h2>Service nicht gefunden</h2>
<p>Der angeforderte Service konnte nicht gefunden werden.</p>
<a href="leads.html" class="cta-btn secondary">Zurück zum Dashboard</a>
</div>
`;
}
});

View File

@@ -1,203 +0,0 @@
// lead-details.js
document.addEventListener("DOMContentLoaded", function() {
const urlParams = new URLSearchParams(window.location.search);
const leadId = urlParams.get('id');
const detailsContainer = document.getElementById('leadDetailsContent');
function getLeads() {
const storedLeads = localStorage.getItem('myLeads');
if (storedLeads) {
return JSON.parse(storedLeads);
} else {
return [];
}
}
function getStatusClass(status) {
const statusClasses = {
'neu': 'status-new',
'in-bearbeitung': 'status-in-progress',
'abgeschlossen': 'status-completed',
'storniert': 'status-cancelled'
};
return statusClasses[status] || 'status-new';
}
function formatDate(dateString) {
const date = new Date(dateString);
return date.toLocaleDateString('de-DE', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
}
if (leadId && detailsContainer) {
const leadsData = getLeads();
const lead = leadsData.find(l => l.id == leadId);
if (lead) {
detailsContainer.innerHTML = `
<div class="lead-details-card">
<!-- Status Section -->
<div class="detail-section">
<h2 class="section-title">Status</h2>
<div class="status-container">
<span class="status-badge ${getStatusClass(lead.status)}">${lead.statusText}</span>
<p class="status-info">Letzte Aktualisierung: ${formatDate(lead.datum)}</p>
</div>
</div>
<!-- Contact Information -->
<div class="detail-section">
<h2 class="section-title">Kontaktinformationen</h2>
<div class="info-grid">
<div class="info-item">
<div class="info-label">Name</div>
<div class="info-value">${lead.name || 'Nicht angegeben'}</div>
</div>
<div class="info-item">
<div class="info-label">Organisation</div>
<div class="info-value">${lead.organisation || 'Nicht angegeben'}</div>
</div>
<div class="info-item">
<div class="info-label">Kontakt</div>
<div class="info-value">${lead.contact || 'Nicht angegeben'}</div>
</div>
<div class="info-item">
<div class="info-label">Budget</div>
<div class="info-value">${lead.budget || 'Nicht angegeben'}</div>
</div>
</div>
</div>
<!-- Service Information -->
<div class="detail-section">
<h2 class="section-title">Dienstleistung</h2>
<div class="service-info">
<div class="service-icon">${getServiceIcon(lead.dienstleistung)}</div>
<div class="service-details">
<h3 class="service-title">${lead.dienstleistung}</h3>
<p class="service-description">${getServiceDescription(lead.dienstleistung)}</p>
</div>
</div>
</div>
<!-- Project Description -->
${lead.description ? `
<div class="detail-section">
<h2 class="section-title">Projektbeschreibung</h2>
<div class="description-box">
<p class="description-text">${lead.description}</p>
</div>
</div>
` : ''}
<!-- Timeline -->
<div class="detail-section">
<h2 class="section-title">Zeitstrahl</h2>
<div class="timeline">
<div class="timeline-item active">
<div class="timeline-dot"></div>
<div class="timeline-content">
<h4>Anfrage erhalten</h4>
<p>${formatDate(lead.datum)}</p>
</div>
</div>
<div class="timeline-item ${lead.status !== 'neu' ? 'active' : ''}">
<div class="timeline-dot"></div>
<div class="timeline-content">
<h4>In Bearbeitung</h4>
<p>${lead.status !== 'neu' ? 'Anfrage wird bearbeitet' : 'Ausstehend'}</p>
</div>
</div>
<div class="timeline-item ${lead.status === 'abgeschlossen' ? 'active' : ''}">
<div class="timeline-dot"></div>
<div class="timeline-content">
<h4>Abgeschlossen</h4>
<p>${lead.status === 'abgeschlossen' ? 'Projekt erfolgreich abgeschlossen' : 'Ausstehend'}</p>
</div>
</div>
</div>
</div>
<!-- Actions -->
<div class="detail-section">
<h2 class="section-title">Aktionen</h2>
<div class="action-buttons">
<button class="action-btn primary" onclick="window.print()">
🖨️ Details drucken
</button>
<button class="action-btn secondary" onclick="shareLead()">
📤 Teilen
</button>
<button class="action-btn secondary" onclick="exportLead()">
📄 Exportieren
</button>
</div>
</div>
</div>
`;
// Update page title
document.title = `Profice - Anfrage von ${lead.name || 'Unbekannt'}`;
} else {
detailsContainer.innerHTML = `
<div class="error-message">
<h2>Anfrage nicht gefunden</h2>
<p>Die angeforderte Anfrage konnte nicht gefunden werden.</p>
<a href="leads.html" class="cta-btn secondary">Zurück zum Dashboard</a>
</div>
`;
}
} else {
detailsContainer.innerHTML = `
<div class="error-message">
<h2>Keine Anfrage-ID angegeben</h2>
<p>Bitte navigieren Sie über das Leads Dashboard zu den Details.</p>
<a href="leads.html" class="cta-btn secondary">Zum Dashboard</a>
</div>
`;
}
});
function getServiceIcon(service) {
const icons = {
'Website': '🌐',
'KI Integration': '🤖',
'Automatisation': '⚙️',
'Unabhängige Wahl': '🎯'
};
return icons[service] || '📋';
}
function getServiceDescription(service) {
const descriptions = {
'Website': 'Moderne, responsive Webseiten, die konvertieren und Ihre Marke perfekt repräsentieren.',
'KI Integration': 'Nutzen Sie die Kraft künstlicher Intelligenz, um Ihre Daten besser zu verstehen und Prozesse zu optimieren.',
'Automatisation': 'Sparen Sie Zeit und Ressourcen durch intelligente Workflow-Automatisierungen.',
'Unabhängige Wahl': 'Maßgeschneiderte Lösungen für Ihre spezifischen Anforderungen.'
};
return descriptions[service] || 'Individuelle Dienstleistung.';
}
function shareLead() {
if (navigator.share) {
navigator.share({
title: document.title,
text: 'Details meiner Projektanfrage bei Profice',
url: window.location.href
});
} else {
// Fallback for browsers that don't support Web Share API
navigator.clipboard.writeText(window.location.href);
alert('Link wurde in die Zwischenablage kopiert!');
}
}
function exportLead() {
window.print();
}