Posthog + Unternehmensanfrage
This commit is contained in:
parent
1be8b2e9bd
commit
69f3e1b14f
|
|
@ -0,0 +1,55 @@
|
||||||
|
# E-Mail Setup für Unternehmensanmeldungen
|
||||||
|
|
||||||
|
## Aktuelle Lösung
|
||||||
|
|
||||||
|
Die Formular-Daten werden derzeit in der Browser-Konsole geloggt. Um E-Mails an `knuth.timo@gmail.com` zu senden, haben Sie mehrere Optionen:
|
||||||
|
|
||||||
|
## Option 1: EmailJS (Empfohlen - Kostenlos)
|
||||||
|
|
||||||
|
1. Gehen Sie zu [https://www.emailjs.com/](https://www.emailjs.com/)
|
||||||
|
2. Erstellen Sie ein kostenloses Konto
|
||||||
|
3. Verbinden Sie Ihren Gmail-Account
|
||||||
|
4. Erstellen Sie eine E-Mail-Vorlage
|
||||||
|
5. Ersetzen Sie die Platzhalter in `src/lib/emailService.ts`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
service_id: 'Ihr_Service_ID',
|
||||||
|
template_id: 'Ihr_Template_ID',
|
||||||
|
user_id: 'Ihr_User_ID'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Option 2: Webhook.site (Einfach)
|
||||||
|
|
||||||
|
1. Gehen Sie zu [https://webhook.site/](https://webhook.site/)
|
||||||
|
2. Kopieren Sie die Webhook-URL
|
||||||
|
3. Ersetzen Sie `'https://webhook.site/your-webhook-url'` in `src/lib/emailService.ts`
|
||||||
|
4. Die Daten werden an die Webhook-URL gesendet
|
||||||
|
|
||||||
|
## Option 3: Zapier (Automatisierung)
|
||||||
|
|
||||||
|
1. Erstellen Sie ein Zapier-Konto
|
||||||
|
2. Erstellen Sie einen "Webhook" Trigger
|
||||||
|
3. Verbinden Sie ihn mit Gmail
|
||||||
|
4. Verwenden Sie die Webhook-URL in der Anwendung
|
||||||
|
|
||||||
|
## Option 4: Netlify Forms (Wenn auf Netlify gehostet)
|
||||||
|
|
||||||
|
Fügen Sie `netlify` zu den Form-Attributen hinzu:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<form name="company-registration" method="POST" data-netlify="true">
|
||||||
|
```
|
||||||
|
|
||||||
|
## Aktuelle Implementierung
|
||||||
|
|
||||||
|
Die Daten werden derzeit in der Browser-Konsole ausgegeben. Öffnen Sie die Entwicklertools (F12) und schauen Sie in die Konsole, um die Formular-Daten zu sehen.
|
||||||
|
|
||||||
|
## PostHog Tracking
|
||||||
|
|
||||||
|
Die folgenden Events werden getrackt:
|
||||||
|
- `company_registration_started` - Formular wird abgesendet
|
||||||
|
- `company_registration_completed` - Erfolgreiche Übermittlung
|
||||||
|
- `company_registration_failed` - Fehler bei der Übermittlung
|
||||||
|
- `experience_selected` - Erfahrungslevel ausgewählt
|
||||||
|
- `energy_type_selected` - Energieart ausgewählt
|
||||||
|
- `service_selected` - Service ausgewählt
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
# E-Mail-Lösung für Unternehmensanmeldungen
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
Webhook.site empfängt nur HTTP-Requests, aber leitet keine E-Mails weiter.
|
||||||
|
|
||||||
|
## Lösung: EmailJS (Kostenlos & Einfach)
|
||||||
|
|
||||||
|
### Schritt 1: EmailJS Account erstellen
|
||||||
|
1. Gehen Sie zu [https://www.emailjs.com/](https://www.emailjs.com/)
|
||||||
|
2. Klicken Sie auf "Sign Up" (kostenlos)
|
||||||
|
3. Erstellen Sie ein Konto
|
||||||
|
|
||||||
|
### Schritt 2: E-Mail-Service einrichten
|
||||||
|
1. **Dashboard** → **Email Services** → **Add New Service**
|
||||||
|
2. Wählen Sie **Gmail**
|
||||||
|
3. Verbinden Sie Ihr Gmail-Konto (`knuth.timo@gmail.com`)
|
||||||
|
4. Notieren Sie sich die **Service ID** (z.B. `service_xxxxxxx`)
|
||||||
|
|
||||||
|
### Schritt 3: E-Mail-Vorlage erstellen
|
||||||
|
1. **Dashboard** → **Email Templates** → **Create New Template**
|
||||||
|
2. **Template ID:** `template_company_registration`
|
||||||
|
3. **Subject:** `Neue Unternehmensanmeldung - EnergieProfis`
|
||||||
|
4. **Content:**
|
||||||
|
```
|
||||||
|
Neue Unternehmensanmeldung
|
||||||
|
|
||||||
|
Firmenname: {{company_name}}
|
||||||
|
Ansprechpartner: {{contact_person}}
|
||||||
|
E-Mail: {{email}}
|
||||||
|
Telefon: {{phone}}
|
||||||
|
Website: {{website}}
|
||||||
|
PLZ: {{zip_code}}
|
||||||
|
Stadt: {{city}}
|
||||||
|
Energiearten: {{energy_types}}
|
||||||
|
Leistungen: {{services}}
|
||||||
|
Jahre Erfahrung: {{experience}}
|
||||||
|
Einzugsgebiet: {{coverage_area}}
|
||||||
|
Kontaktpräferenz: {{contact_preference}}
|
||||||
|
Newsletter: {{newsletter}}
|
||||||
|
|
||||||
|
Unternehmensbeschreibung:
|
||||||
|
{{description}}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Schritt 4: User ID finden
|
||||||
|
1. **Dashboard** → **Account** → **General**
|
||||||
|
2. Kopieren Sie Ihre **Public Key** (User ID)
|
||||||
|
|
||||||
|
### Schritt 5: Code aktualisieren
|
||||||
|
Ersetzen Sie in `src/lib/emailService.ts`:
|
||||||
|
```typescript
|
||||||
|
user_id: 'YOUR_EMAILJS_USER_ID' // Mit Ihrer echten User ID
|
||||||
|
```
|
||||||
|
|
||||||
|
## Alternative: Zapier (Automatisiert)
|
||||||
|
|
||||||
|
### Schritt 1: Zapier Account
|
||||||
|
1. Gehen Sie zu [https://zapier.com](https://zapier.com)
|
||||||
|
2. Erstellen Sie ein kostenloses Konto
|
||||||
|
|
||||||
|
### Schritt 2: Zap erstellen
|
||||||
|
1. **Create Zap**
|
||||||
|
2. **Trigger:** "Webhooks by Zapier" → "Catch Hook"
|
||||||
|
3. **Action:** "Gmail" → "Send Email"
|
||||||
|
4. **Konfiguration:**
|
||||||
|
- **To:** `knuth.timo@gmail.com`
|
||||||
|
- **Subject:** `Neue Unternehmensanmeldung - EnergieProfis`
|
||||||
|
- **Body:** Verwenden Sie die Webhook-Daten
|
||||||
|
|
||||||
|
### Schritt 3: Webhook-URL ersetzen
|
||||||
|
Ersetzen Sie die Webhook-URL in `src/lib/emailService.ts` mit der Zapier-URL.
|
||||||
|
|
||||||
|
## Sofortige Lösung: Console Logging
|
||||||
|
|
||||||
|
Bis Sie einen E-Mail-Service einrichten, werden alle Daten in der Browser-Konsole geloggt:
|
||||||
|
1. Öffnen Sie F12 (Entwicklertools)
|
||||||
|
2. Gehen Sie zum "Console" Tab
|
||||||
|
3. Alle Formular-Daten werden dort angezeigt
|
||||||
|
|
||||||
|
## Status
|
||||||
|
✅ **Webhook funktioniert** - Daten werden empfangen
|
||||||
|
⚠️ **E-Mail-Weiterleitung** - Benötigt E-Mail-Service
|
||||||
|
✅ **PostHog Analytics** - Funktioniert
|
||||||
|
✅ **Dropdown ohne Animation** - Funktioniert
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
# PostHog Analytics Setup
|
||||||
|
|
||||||
|
PostHog has been successfully integrated into the Energie Finder Profi project.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
- **API Key**: `phc_jIkj0hQSY670vRaUVjSRSDOqmLCDGkL6GJy44iqE84M`
|
||||||
|
- **Host**: `https://app.posthog.com`
|
||||||
|
- **Initialization**: PostHog is automatically initialized in `main.tsx`
|
||||||
|
|
||||||
|
## Files Added/Modified
|
||||||
|
|
||||||
|
1. **`src/lib/posthog.ts`** - PostHog configuration and initialization
|
||||||
|
2. **`src/hooks/usePostHog.ts`** - React hook for easy PostHog usage
|
||||||
|
3. **`src/main.tsx`** - PostHog initialization on app start
|
||||||
|
4. **`src/components/HeroSection.tsx`** - Example tracking implementation
|
||||||
|
5. **`package.json`** - Added posthog-js dependency
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Basic Event Tracking
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { usePostHog } from '@/hooks/usePostHog'
|
||||||
|
|
||||||
|
const MyComponent = () => {
|
||||||
|
const posthog = usePostHog()
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
posthog.capture('button_clicked', {
|
||||||
|
button_name: 'search',
|
||||||
|
page: 'home'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return <button onClick={handleClick}>Click me</button>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### User Identification
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
const posthog = usePostHog()
|
||||||
|
|
||||||
|
// Identify a user
|
||||||
|
posthog.identify('user_123', {
|
||||||
|
email: 'user@example.com',
|
||||||
|
name: 'John Doe'
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Feature Flags
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
const posthog = usePostHog()
|
||||||
|
|
||||||
|
// Check if feature is enabled
|
||||||
|
const isNewFeatureEnabled = posthog.isFeatureEnabled('new_feature')
|
||||||
|
|
||||||
|
// Get feature flag value
|
||||||
|
const featureValue = posthog.getFeatureFlag('feature_with_value')
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
You can optionally set the PostHog API key via environment variable:
|
||||||
|
|
||||||
|
```env
|
||||||
|
VITE_POSTHOG_API_KEY=phc_jIkj0hQSY670vRaUVjSRSDOqmLCDGkL6GJy44iqE84M
|
||||||
|
```
|
||||||
|
|
||||||
|
## Current Tracking
|
||||||
|
|
||||||
|
The following events are currently being tracked:
|
||||||
|
|
||||||
|
- `hero_search_clicked` - When user clicks "Installateur Finden" in hero section
|
||||||
|
- `hero_view_all_clicked` - When user clicks "Alle Installateure Ansehen"
|
||||||
|
|
||||||
|
## PostHog Dashboard
|
||||||
|
|
||||||
|
Visit [https://app.posthog.com](https://app.posthog.com) to view analytics data, create funnels, and set up feature flags.
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
"input-otp": "^1.4.2",
|
"input-otp": "^1.4.2",
|
||||||
"lucide-react": "^0.462.0",
|
"lucide-react": "^0.462.0",
|
||||||
"next-themes": "^0.3.0",
|
"next-themes": "^0.3.0",
|
||||||
|
"posthog-js": "^1.200.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-day-picker": "^8.10.1",
|
"react-day-picker": "^8.10.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
|
@ -988,6 +989,12 @@
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@posthog/core": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-hWk3rUtJl2crQK0WNmwg13n82hnTwB99BT99/XI5gZSvIlYZ1TPmMZE8H2dhJJ98J/rm9vYJ/UXNzw3RV5HTpQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/number": {
|
"node_modules/@radix-ui/number": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
|
||||||
|
|
@ -3724,6 +3731,17 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/core-js": {
|
||||||
|
"version": "3.45.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.45.1.tgz",
|
||||||
|
"integrity": "sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/core-js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cross-spawn": {
|
"node_modules/cross-spawn": {
|
||||||
"version": "7.0.6",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||||
|
|
@ -4327,6 +4345,12 @@
|
||||||
"reusify": "^1.0.4"
|
"reusify": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fflate": {
|
||||||
|
"version": "0.4.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz",
|
||||||
|
"integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/file-entry-cache": {
|
"node_modules/file-entry-cache": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
|
||||||
|
|
@ -5801,6 +5825,41 @@
|
||||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/posthog-js": {
|
||||||
|
"version": "1.261.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.261.7.tgz",
|
||||||
|
"integrity": "sha512-Fjpbz6VfIMsEbKIN/UyTWhU1DGgVIngqoRjPGRolemIMOVzTfI77OZq8WwiBhMug+rU+wNhGCQhC41qRlR5CxA==",
|
||||||
|
"license": "SEE LICENSE IN LICENSE",
|
||||||
|
"dependencies": {
|
||||||
|
"@posthog/core": "1.0.2",
|
||||||
|
"core-js": "^3.38.1",
|
||||||
|
"fflate": "^0.4.8",
|
||||||
|
"preact": "^10.19.3",
|
||||||
|
"web-vitals": "^4.2.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@rrweb/types": "2.0.0-alpha.17",
|
||||||
|
"rrweb-snapshot": "2.0.0-alpha.17"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@rrweb/types": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"rrweb-snapshot": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/preact": {
|
||||||
|
"version": "10.27.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/preact/-/preact-10.27.1.tgz",
|
||||||
|
"integrity": "sha512-V79raXEWch/rbqoNc7nT9E4ep7lu+mI3+sBmfRD4i1M73R3WLYcCtdI0ibxGVf4eQL8ZIz2nFacqEC+rmnOORQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/preact"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prelude-ls": {
|
"node_modules/prelude-ls": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||||
|
|
@ -7314,6 +7373,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/web-vitals": {
|
||||||
|
"version": "4.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz",
|
||||||
|
"integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
"node_modules/webidl-conversions": {
|
"node_modules/webidl-conversions": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@
|
||||||
"input-otp": "^1.4.2",
|
"input-otp": "^1.4.2",
|
||||||
"lucide-react": "^0.462.0",
|
"lucide-react": "^0.462.0",
|
||||||
"next-themes": "^0.3.0",
|
"next-themes": "^0.3.0",
|
||||||
|
"posthog-js": "^1.200.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-day-picker": "^8.10.1",
|
"react-day-picker": "^8.10.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@ import Wind from "./pages/Wind";
|
||||||
import InstallateurFinden from "./pages/InstallateurFinden";
|
import InstallateurFinden from "./pages/InstallateurFinden";
|
||||||
import KostenloseBeratung from "./pages/KostenloseBeratung";
|
import KostenloseBeratung from "./pages/KostenloseBeratung";
|
||||||
import UnternehmenListen from "./pages/UnternehmenListen";
|
import UnternehmenListen from "./pages/UnternehmenListen";
|
||||||
|
import Impressum from "./pages/Impressum";
|
||||||
|
import Datenschutz from "./pages/Datenschutz";
|
||||||
|
import CookieEinstellungen from "./pages/CookieEinstellungen";
|
||||||
import NotFound from "./pages/NotFound";
|
import NotFound from "./pages/NotFound";
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
@ -26,6 +29,9 @@ const App = () => (
|
||||||
<Route path="/installateur-finden" element={<InstallateurFinden />} />
|
<Route path="/installateur-finden" element={<InstallateurFinden />} />
|
||||||
<Route path="/kostenlose-beratung" element={<KostenloseBeratung />} />
|
<Route path="/kostenlose-beratung" element={<KostenloseBeratung />} />
|
||||||
<Route path="/unternehmen-listen" element={<UnternehmenListen />} />
|
<Route path="/unternehmen-listen" element={<UnternehmenListen />} />
|
||||||
|
<Route path="/impressum" element={<Impressum />} />
|
||||||
|
<Route path="/datenschutz" element={<Datenschutz />} />
|
||||||
|
<Route path="/cookie-einstellungen" element={<CookieEinstellungen />} />
|
||||||
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
|
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
|
||||||
<Route path="*" element={<NotFound />} />
|
<Route path="*" element={<NotFound />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ const Footer = () => {
|
||||||
return (
|
return (
|
||||||
<footer className="bg-gray-900 text-white mt-20">
|
<footer className="bg-gray-900 text-white mt-20">
|
||||||
<div className="container mx-auto px-4 py-12">
|
<div className="container mx-auto px-4 py-12">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||||
{/* Company Info */}
|
{/* Company Info */}
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
|
@ -137,28 +137,6 @@ const Footer = () => {
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Contact Info */}
|
|
||||||
<div className="space-y-4">
|
|
||||||
<h3 className="text-lg font-semibold">Kontakt</h3>
|
|
||||||
<div className="space-y-3 text-sm">
|
|
||||||
<div className="flex items-center gap-3 text-gray-300">
|
|
||||||
<Mail className="w-4 h-4" />
|
|
||||||
<span>info@energieprofis.de</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-3 text-gray-300">
|
|
||||||
<Phone className="w-4 h-4" />
|
|
||||||
<span>+49 (0) 800 123 456</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-start gap-3 text-gray-300">
|
|
||||||
<MapPin className="w-4 h-4 mt-0.5" />
|
|
||||||
<span>
|
|
||||||
EnergieProfis GmbH<br />
|
|
||||||
Musterstraße 123<br />
|
|
||||||
10115 Berlin
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Bottom Section */}
|
{/* Bottom Section */}
|
||||||
|
|
@ -168,18 +146,27 @@ const Footer = () => {
|
||||||
© 2025 EnergieProfis. Alle Rechte vorbehalten.
|
© 2025 EnergieProfis. Alle Rechte vorbehalten.
|
||||||
</div>
|
</div>
|
||||||
<div className="flex space-x-6 text-sm">
|
<div className="flex space-x-6 text-sm">
|
||||||
<a href="/" className="text-gray-400 hover:text-white transition-colors">
|
<Link
|
||||||
|
to="/impressum"
|
||||||
|
className="text-gray-400 hover:text-white transition-colors"
|
||||||
|
onClick={() => window.scrollTo(0, 0)}
|
||||||
|
>
|
||||||
Impressum
|
Impressum
|
||||||
</a>
|
</Link>
|
||||||
<a href="/" className="text-gray-400 hover:text-white transition-colors">
|
<Link
|
||||||
|
to="/datenschutz"
|
||||||
|
className="text-gray-400 hover:text-white transition-colors"
|
||||||
|
onClick={() => window.scrollTo(0, 0)}
|
||||||
|
>
|
||||||
Datenschutz
|
Datenschutz
|
||||||
</a>
|
</Link>
|
||||||
<a href="/" className="text-gray-400 hover:text-white transition-colors">
|
<Link
|
||||||
AGB
|
to="/cookie-einstellungen"
|
||||||
</a>
|
className="text-gray-400 hover:text-white transition-colors"
|
||||||
<a href="/" className="text-gray-400 hover:text-white transition-colors">
|
onClick={() => window.scrollTo(0, 0)}
|
||||||
|
>
|
||||||
Cookie-Einstellungen
|
Cookie-Einstellungen
|
||||||
</a>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,25 @@ import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Search, MapPin, Zap, ArrowRight, Calculator, Award, Shield } from "lucide-react";
|
import { Search, MapPin, Zap, ArrowRight, Calculator, Award, Shield } from "lucide-react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
import { usePostHog } from "@/hooks/usePostHog";
|
||||||
|
|
||||||
const HeroSection = () => {
|
const HeroSection = () => {
|
||||||
|
const posthog = usePostHog();
|
||||||
|
|
||||||
|
const handleSearchClick = () => {
|
||||||
|
posthog.capture('hero_search_clicked', {
|
||||||
|
location: 'hero_section',
|
||||||
|
action: 'search_installers'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleViewAllClick = () => {
|
||||||
|
posthog.capture('hero_view_all_clicked', {
|
||||||
|
location: 'hero_section',
|
||||||
|
action: 'view_all_installers'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="relative min-h-[600px] flex items-center overflow-hidden">
|
<section className="relative min-h-[600px] flex items-center overflow-hidden">
|
||||||
{/* Background Image with Minimal Overlay */}
|
{/* Background Image with Minimal Overlay */}
|
||||||
|
|
@ -86,6 +103,7 @@ const HeroSection = () => {
|
||||||
variant="hero"
|
variant="hero"
|
||||||
size="lg"
|
size="lg"
|
||||||
className="bg-cyan-600 hover:bg-cyan-700 text-white border-0 shadow-lg hover:shadow-xl transition-all duration-300"
|
className="bg-cyan-600 hover:bg-cyan-700 text-white border-0 shadow-lg hover:shadow-xl transition-all duration-300"
|
||||||
|
onClick={handleSearchClick}
|
||||||
>
|
>
|
||||||
<Link to="/installateur-finden">
|
<Link to="/installateur-finden">
|
||||||
<Search className="w-5 h-5 mr-2" />
|
<Search className="w-5 h-5 mr-2" />
|
||||||
|
|
@ -146,6 +164,7 @@ const HeroSection = () => {
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="lg"
|
size="lg"
|
||||||
className="border-2 border-white/40 text-white hover:bg-white hover:text-primary bg-white/10 backdrop-blur-sm hover:shadow-lg transition-all duration-300"
|
className="border-2 border-white/40 text-white hover:bg-white hover:text-primary bg-white/10 backdrop-blur-sm hover:shadow-lg transition-all duration-300"
|
||||||
|
onClick={handleViewAllClick}
|
||||||
>
|
>
|
||||||
<Link to="/installateur-finden" className="flex items-center">
|
<Link to="/installateur-finden" className="flex items-center">
|
||||||
Alle Installateure Ansehen
|
Alle Installateure Ansehen
|
||||||
|
|
|
||||||
|
|
@ -73,12 +73,20 @@ const SelectContent = React.forwardRef<
|
||||||
<SelectPrimitive.Content
|
<SelectPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md [&]:!transition-none [&]:!duration-0 [&]:!animate-none",
|
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md",
|
||||||
|
"!transition-none !duration-0 !animate-none",
|
||||||
|
"data-[state=open]:!animate-none data-[state=closed]:!animate-none",
|
||||||
|
"data-[side=bottom]:!translate-y-0 data-[side=left]:!translate-x-0 data-[side=right]:!translate-x-0 data-[side=top]:!translate-y-0",
|
||||||
position === "popper" &&
|
position === "popper" &&
|
||||||
"",
|
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
position={position}
|
position={position}
|
||||||
|
style={{
|
||||||
|
animation: 'none !important',
|
||||||
|
transition: 'none !important',
|
||||||
|
transform: 'none !important'
|
||||||
|
}}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<SelectScrollUpButton />
|
<SelectScrollUpButton />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
import * as React from "react"
|
||||||
|
import { ChevronDown } from "lucide-react"
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
interface SimpleSelectProps {
|
||||||
|
value: string
|
||||||
|
onValueChange: (value: string) => void
|
||||||
|
placeholder?: string
|
||||||
|
children: React.ReactNode
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const SimpleSelect = React.forwardRef<HTMLDivElement, SimpleSelectProps>(
|
||||||
|
({ value, onValueChange, placeholder, children, className, ...props }, ref) => {
|
||||||
|
const [isOpen, setIsOpen] = React.useState(false)
|
||||||
|
const [selectedValue, setSelectedValue] = React.useState(value)
|
||||||
|
const [selectedLabel, setSelectedLabel] = React.useState("")
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
setSelectedValue(value)
|
||||||
|
// Find the selected option label
|
||||||
|
const selectedOption = React.Children.toArray(children).find(
|
||||||
|
(child) => React.isValidElement(child) && child.props.value === value
|
||||||
|
)
|
||||||
|
if (selectedOption && React.isValidElement(selectedOption)) {
|
||||||
|
setSelectedLabel(selectedOption.props.children)
|
||||||
|
}
|
||||||
|
}, [value, children])
|
||||||
|
|
||||||
|
const handleSelect = (newValue: string, newLabel: string) => {
|
||||||
|
setSelectedValue(newValue)
|
||||||
|
setSelectedLabel(newLabel)
|
||||||
|
setIsOpen(false)
|
||||||
|
onValueChange(newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={ref} className={cn("relative", className)} {...props}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setIsOpen(!isOpen)}
|
||||||
|
className={cn(
|
||||||
|
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<span className={selectedValue ? "text-foreground" : "text-muted-foreground"}>
|
||||||
|
{selectedLabel || placeholder}
|
||||||
|
</span>
|
||||||
|
<ChevronDown className="h-4 w-4 opacity-50" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{isOpen && (
|
||||||
|
<div className="absolute z-50 w-full mt-1 bg-popover border border-border rounded-md shadow-md">
|
||||||
|
<div className="p-1">
|
||||||
|
{React.Children.map(children, (child) => {
|
||||||
|
if (React.isValidElement(child)) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={child.props.value}
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleSelect(child.props.value, child.props.children)}
|
||||||
|
className={cn(
|
||||||
|
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
|
||||||
|
selectedValue === child.props.value && "bg-accent text-accent-foreground"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||||
|
{selectedValue === child.props.value && (
|
||||||
|
<svg className="h-4 w-4" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
{child.props.children}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return child
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Click outside to close */}
|
||||||
|
{isOpen && (
|
||||||
|
<div
|
||||||
|
className="fixed inset-0 z-40"
|
||||||
|
onClick={() => setIsOpen(false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
SimpleSelect.displayName = "SimpleSelect"
|
||||||
|
|
||||||
|
interface SimpleSelectItemProps {
|
||||||
|
value: string
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const SimpleSelectItem = ({ value, children }: SimpleSelectItemProps) => {
|
||||||
|
return <div data-value={value}>{children}</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleSelectItem.displayName = "SimpleSelectItem"
|
||||||
|
|
||||||
|
export { SimpleSelect, SimpleSelectItem }
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
import { posthog } from '../lib/posthog'
|
||||||
|
|
||||||
|
export const usePostHog = () => {
|
||||||
|
useEffect(() => {
|
||||||
|
// PostHog is already initialized in main.tsx
|
||||||
|
return () => {
|
||||||
|
// Cleanup if needed
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return {
|
||||||
|
capture: (event: string, properties?: Record<string, any>) => {
|
||||||
|
posthog.capture(event, properties)
|
||||||
|
},
|
||||||
|
identify: (userId: string, properties?: Record<string, any>) => {
|
||||||
|
posthog.identify(userId, properties)
|
||||||
|
},
|
||||||
|
reset: () => {
|
||||||
|
posthog.reset()
|
||||||
|
},
|
||||||
|
isFeatureEnabled: (flag: string) => {
|
||||||
|
return posthog.isFeatureEnabled(flag)
|
||||||
|
},
|
||||||
|
getFeatureFlag: (flag: string) => {
|
||||||
|
return posthog.getFeatureFlag(flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
// Simple email service for form submissions
|
||||||
|
// This uses a free webhook service to send emails
|
||||||
|
|
||||||
|
export const sendCompanyRegistrationEmail = async (formData: any) => {
|
||||||
|
const emailData = {
|
||||||
|
to: 'knuth.timo@gmail.com',
|
||||||
|
subject: 'Neue Unternehmensanmeldung - EnergieProfis',
|
||||||
|
message: `
|
||||||
|
Neue Unternehmensanmeldung
|
||||||
|
|
||||||
|
Firmenname: ${formData.companyName}
|
||||||
|
Ansprechpartner: ${formData.contactPerson}
|
||||||
|
E-Mail: ${formData.email}
|
||||||
|
Telefon: ${formData.phone}
|
||||||
|
Website: ${formData.website || 'Nicht angegeben'}
|
||||||
|
PLZ: ${formData.zipCode}
|
||||||
|
Stadt: ${formData.city}
|
||||||
|
Energiearten: ${formData.energyTypes.join(', ')}
|
||||||
|
Leistungen: ${formData.services.join(', ')}
|
||||||
|
Jahre Erfahrung: ${formData.experience}
|
||||||
|
Einzugsgebiet: ${formData.coverageArea || 'Nicht angegeben'}
|
||||||
|
Kontaktpräferenz: ${formData.contactPreference}
|
||||||
|
Newsletter: ${formData.newsletter ? 'Ja' : 'Nein'}
|
||||||
|
|
||||||
|
Unternehmensbeschreibung:
|
||||||
|
${formData.description}
|
||||||
|
`
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Log the data for now (this will show in console)
|
||||||
|
console.log('=== NEUE UNTERNEHMENSANMELDUNG ===');
|
||||||
|
console.log('📧 An: knuth.timo@gmail.com');
|
||||||
|
console.log('📋 Betreff: Neue Unternehmensanmeldung - EnergieProfis');
|
||||||
|
console.log('📄 Daten:', formData);
|
||||||
|
console.log('=====================================');
|
||||||
|
|
||||||
|
// Try to send email using EmailJS
|
||||||
|
try {
|
||||||
|
const emailResponse = await fetch('https://api.emailjs.com/api/v1.0/email/send', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
service_id: 'service_09n6j0x',
|
||||||
|
template_id: 'template_a5sc93m',
|
||||||
|
user_id: 'aAqMJarAgKThnW487',
|
||||||
|
template_params: {
|
||||||
|
to_email: emailData.to,
|
||||||
|
subject: emailData.subject,
|
||||||
|
message: emailData.message,
|
||||||
|
company_name: formData.companyName,
|
||||||
|
contact_person: formData.contactPerson,
|
||||||
|
email: formData.email,
|
||||||
|
phone: formData.phone,
|
||||||
|
website: formData.website || 'Nicht angegeben',
|
||||||
|
zip_code: formData.zipCode,
|
||||||
|
city: formData.city,
|
||||||
|
energy_types: formData.energyTypes.join(', '),
|
||||||
|
services: formData.services.join(', '),
|
||||||
|
experience: formData.experience,
|
||||||
|
coverage_area: formData.coverageArea || 'Nicht angegeben',
|
||||||
|
contact_preference: formData.contactPreference,
|
||||||
|
newsletter: formData.newsletter ? 'Ja' : 'Nein',
|
||||||
|
description: formData.description
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
if (emailResponse.ok) {
|
||||||
|
console.log('✅ E-Mail erfolgreich an knuth.timo@gmail.com gesendet!');
|
||||||
|
return { success: true };
|
||||||
|
} else {
|
||||||
|
const errorText = await emailResponse.text();
|
||||||
|
console.log('⚠️ E-Mail-Service Fehler:', emailResponse.status, errorText);
|
||||||
|
console.log('📧 Daten werden trotzdem geloggt für manuelle Verarbeitung');
|
||||||
|
return { success: false, data: emailData };
|
||||||
|
}
|
||||||
|
} catch (emailError) {
|
||||||
|
console.log('⚠️ E-Mail-Service nicht verfügbar, aber Daten wurden geloggt');
|
||||||
|
return { success: false, data: emailData };
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error sending email:', error);
|
||||||
|
console.log('Form data for manual processing:', emailData);
|
||||||
|
return { success: false, error: error.message, data: emailData };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Alternative: Simple console logging for development
|
||||||
|
export const logCompanyRegistration = (formData: any) => {
|
||||||
|
console.log('=== NEUE UNTERNEHMENSANMELDUNG ===');
|
||||||
|
console.log('Firmenname:', formData.companyName);
|
||||||
|
console.log('Ansprechpartner:', formData.contactPerson);
|
||||||
|
console.log('E-Mail:', formData.email);
|
||||||
|
console.log('Telefon:', formData.phone);
|
||||||
|
console.log('Website:', formData.website || 'Nicht angegeben');
|
||||||
|
console.log('PLZ:', formData.zipCode);
|
||||||
|
console.log('Stadt:', formData.city);
|
||||||
|
console.log('Energiearten:', formData.energyTypes.join(', '));
|
||||||
|
console.log('Leistungen:', formData.services.join(', '));
|
||||||
|
console.log('Jahre Erfahrung:', formData.experience);
|
||||||
|
console.log('Einzugsgebiet:', formData.coverageArea || 'Nicht angegeben');
|
||||||
|
console.log('Kontaktpräferenz:', formData.contactPreference);
|
||||||
|
console.log('Newsletter:', formData.newsletter ? 'Ja' : 'Nein');
|
||||||
|
console.log('Unternehmensbeschreibung:', formData.description);
|
||||||
|
console.log('=====================================');
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
import posthog from 'posthog-js'
|
||||||
|
|
||||||
|
const POSTHOG_API_KEY = import.meta.env.VITE_POSTHOG_API_KEY || 'phc_jIkj0hQSY670vRaUVjSRSDOqmLCDGkL6GJy44iqE84M'
|
||||||
|
|
||||||
|
export const initPostHog = () => {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
posthog.init(POSTHOG_API_KEY, {
|
||||||
|
api_host: 'https://app.posthog.com',
|
||||||
|
person_profiles: 'identified_only',
|
||||||
|
capture_pageview: true,
|
||||||
|
capture_pageleave: true,
|
||||||
|
loaded: (posthog) => {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
console.log('PostHog loaded successfully')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { posthog }
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client'
|
||||||
import App from './App.tsx'
|
import App from './App.tsx'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
|
import { initPostHog } from './lib/posthog'
|
||||||
|
|
||||||
|
// Initialize PostHog
|
||||||
|
initPostHog()
|
||||||
|
|
||||||
createRoot(document.getElementById("root")!).render(<App />);
|
createRoot(document.getElementById("root")!).render(<App />);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,210 @@
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Switch } from "@/components/ui/switch";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import Header from "@/components/Header";
|
||||||
|
import Footer from "@/components/Footer";
|
||||||
|
|
||||||
|
const CookieEinstellungen = () => {
|
||||||
|
const [necessaryCookies, setNecessaryCookies] = useState(true); // Always true, can't be disabled
|
||||||
|
const [analyticsCookies, setAnalyticsCookies] = useState(false);
|
||||||
|
const [marketingCookies, setMarketingCookies] = useState(false);
|
||||||
|
|
||||||
|
const handleSavePreferences = () => {
|
||||||
|
// Save cookie preferences to localStorage
|
||||||
|
localStorage.setItem('cookiePreferences', JSON.stringify({
|
||||||
|
necessary: necessaryCookies,
|
||||||
|
analytics: analyticsCookies,
|
||||||
|
marketing: marketingCookies
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Show success message
|
||||||
|
alert('Ihre Cookie-Einstellungen wurden gespeichert!');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAcceptAll = () => {
|
||||||
|
setAnalyticsCookies(true);
|
||||||
|
setMarketingCookies(true);
|
||||||
|
localStorage.setItem('cookiePreferences', JSON.stringify({
|
||||||
|
necessary: true,
|
||||||
|
analytics: true,
|
||||||
|
marketing: true
|
||||||
|
}));
|
||||||
|
alert('Alle Cookies wurden akzeptiert!');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRejectAll = () => {
|
||||||
|
setAnalyticsCookies(false);
|
||||||
|
setMarketingCookies(false);
|
||||||
|
localStorage.setItem('cookiePreferences', JSON.stringify({
|
||||||
|
necessary: true,
|
||||||
|
analytics: false,
|
||||||
|
marketing: false
|
||||||
|
}));
|
||||||
|
alert('Alle optionalen Cookies wurden abgelehnt!');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-background">
|
||||||
|
<Header />
|
||||||
|
|
||||||
|
<div className="container mx-auto px-4 py-16 mt-16">
|
||||||
|
<div className="max-w-4xl mx-auto">
|
||||||
|
<h1 className="text-4xl font-bold text-foreground mb-8">Cookie-Einstellungen</h1>
|
||||||
|
|
||||||
|
<Card className="mb-8">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Was sind Cookies?</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Cookies sind kleine Textdateien, die auf Ihrem Gerät gespeichert werden, wenn Sie unsere Website besuchen.
|
||||||
|
Sie helfen uns dabei, Ihre Präferenzen zu speichern und die Website für Sie zu verbessern.
|
||||||
|
Wir verwenden verschiedene Arten von Cookies für unterschiedliche Zwecke.
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="mb-8">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Cookie-Kategorien</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-6">
|
||||||
|
{/* Necessary Cookies */}
|
||||||
|
<div className="flex items-center justify-between p-4 border rounded-lg">
|
||||||
|
<div className="flex-1">
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Notwendige Cookies</h3>
|
||||||
|
<p className="text-muted-foreground text-sm">
|
||||||
|
Diese Cookies sind für das Funktionieren der Website unerlässlich. Sie können nicht deaktiviert werden.
|
||||||
|
Sie werden normalerweise nur als Reaktion auf Aktionen gesetzt, die Sie ausführen und die einer Anfrage nach Diensten entsprechen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Switch checked={necessaryCookies} disabled />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Analytics Cookies */}
|
||||||
|
<div className="flex items-center justify-between p-4 border rounded-lg">
|
||||||
|
<div className="flex-1">
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Analyse-Cookies</h3>
|
||||||
|
<p className="text-muted-foreground text-sm">
|
||||||
|
Diese Cookies ermöglichen es uns, die Anzahl der Besucher zu zählen und zu verstehen, wie Besucher mit unserer Website interagieren.
|
||||||
|
Alle Informationen, die diese Cookies sammeln, werden aggregiert und sind daher anonym.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Switch
|
||||||
|
checked={analyticsCookies}
|
||||||
|
onCheckedChange={setAnalyticsCookies}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Marketing Cookies */}
|
||||||
|
<div className="flex items-center justify-between p-4 border rounded-lg">
|
||||||
|
<div className="flex-1">
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Marketing-Cookies</h3>
|
||||||
|
<p className="text-muted-foreground text-sm">
|
||||||
|
Diese Cookies werden verwendet, um Besuchern auf Webseiten zu folgen. Die Absicht ist, Anzeigen zu zeigen,
|
||||||
|
die relevant und ansprechend für den einzelnen Benutzer sind und daher wertvoller für Publisher und Drittanbieter sind.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Switch
|
||||||
|
checked={marketingCookies}
|
||||||
|
onCheckedChange={setMarketingCookies}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="mb-8">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Detaillierte Cookie-Informationen</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Notwendige Cookies</h3>
|
||||||
|
<div className="space-y-2 text-sm">
|
||||||
|
<div className="flex justify-between items-center p-2 bg-gray-50 rounded">
|
||||||
|
<span className="font-medium">session_id</span>
|
||||||
|
<span className="text-muted-foreground">Speichert Ihre Session-ID</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between items-center p-2 bg-gray-50 rounded">
|
||||||
|
<span className="font-medium">cookie_preferences</span>
|
||||||
|
<span className="text-muted-foreground">Speichert Ihre Cookie-Einstellungen</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Analyse-Cookies</h3>
|
||||||
|
<div className="space-y-2 text-sm">
|
||||||
|
<div className="flex justify-between items-center p-2 bg-gray-50 rounded">
|
||||||
|
<span className="font-medium">_ga</span>
|
||||||
|
<span className="text-muted-foreground">Google Analytics - Unterscheidet Benutzer</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between items-center p-2 bg-gray-50 rounded">
|
||||||
|
<span className="font-medium">_gid</span>
|
||||||
|
<span className="text-muted-foreground">Google Analytics - Unterscheidet Benutzer</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Marketing-Cookies</h3>
|
||||||
|
<div className="space-y-2 text-sm">
|
||||||
|
<div className="flex justify-between items-center p-2 bg-gray-50 rounded">
|
||||||
|
<span className="font-medium">_fbp</span>
|
||||||
|
<span className="text-muted-foreground">Facebook Pixel - Verfolgt Besucher</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="mb-8">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Ihre Rechte</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-muted-foreground mb-4">
|
||||||
|
Sie haben das Recht, Ihre Cookie-Einstellungen jederzeit zu ändern. Sie können auch Cookies,
|
||||||
|
die bereits auf Ihrem Gerät gespeichert sind, über Ihren Browser löschen.
|
||||||
|
</p>
|
||||||
|
<div className="space-y-2 text-sm">
|
||||||
|
<p><strong>Chrome:</strong> Einstellungen → Erweitert → Datenschutz und Sicherheit → Cookies und andere Websitedaten</p>
|
||||||
|
<p><strong>Firefox:</strong> Einstellungen → Datenschutz & Sicherheit → Cookies und Website-Daten</p>
|
||||||
|
<p><strong>Safari:</strong> Einstellungen → Datenschutz → Cookies und Website-Daten verwalten</p>
|
||||||
|
<p><strong>Edge:</strong> Einstellungen → Cookies und Websiteberechtigungen → Cookies und gespeicherte Daten</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Action Buttons */}
|
||||||
|
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||||
|
<Button
|
||||||
|
onClick={handleSavePreferences}
|
||||||
|
className="bg-primary hover:bg-primary/90"
|
||||||
|
>
|
||||||
|
Einstellungen speichern
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={handleAcceptAll}
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
Alle akzeptieren
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={handleRejectAll}
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
Alle ablehnen
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CookieEinstellungen;
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import Header from "@/components/Header";
|
||||||
|
import Footer from "@/components/Footer";
|
||||||
|
|
||||||
|
const Datenschutz = () => {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-background">
|
||||||
|
<Header />
|
||||||
|
|
||||||
|
<div className="container mx-auto px-4 py-16 mt-16">
|
||||||
|
<div className="max-w-4xl mx-auto">
|
||||||
|
<h1 className="text-4xl font-bold text-foreground mb-8">Datenschutzerklärung</h1>
|
||||||
|
|
||||||
|
<Card className="mb-8">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>1. Datenschutz auf einen Blick</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Allgemeine Hinweise</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Die folgenden Hinweise geben einen einfachen Überblick darüber, was mit Ihren personenbezogenen Daten passiert, wenn Sie diese Website besuchen. Personenbezogene Daten sind alle Daten, mit denen Sie persönlich identifiziert werden können. Ausführliche Informationen zum Thema Datenschutz entnehmen Sie unserer unter diesem Text aufgeführten Datenschutzerklärung.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Datenerfassung auf dieser Website</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Die Datenverarbeitung auf dieser Website erfolgt durch den Websitebetreiber. Dessen Kontaktdaten können Sie dem Abschnitt „Hinweis zur Verantwortlichen Stelle" in dieser Datenschutzerklärung entnehmen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="mb-8">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>2. Allgemeine Hinweise und Pflichtinformationen</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Datenschutz</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend den gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Hinweis zur verantwortlichen Stelle</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Die verantwortliche Stelle für die Datenverarbeitung auf dieser Website ist der Betreiber dieser Website.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Speicherdauer</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Soweit innerhalb dieser Datenschutzerklärung keine speziellere Speicherdauer genannt wurde, verbleiben Ihre personenbezogenen Daten bei uns, bis der Zweck für die Datenverarbeitung entfällt. Wenn Sie ein berechtigtes Löschersuchen geltend machen oder eine Einwilligung zur Datenverarbeitung widerrufen, werden Ihre Daten gelöscht, sofern wir keine anderen rechtlich zulässigen Gründe für die Speicherung Ihrer personenbezogenen Daten haben.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="mb-8">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>3. Datenerfassung auf dieser Website</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Server-Log-Dateien</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log-Dateien, die Ihr Browser automatisch an uns übermittelt. Dies sind:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc list-inside text-muted-foreground mt-2 space-y-1">
|
||||||
|
<li>Browsertyp und Browserversion</li>
|
||||||
|
<li>verwendetes Betriebssystem</li>
|
||||||
|
<li>Referrer URL</li>
|
||||||
|
<li>Hostname des zugreifenden Rechners</li>
|
||||||
|
<li>Uhrzeit der Serveranfrage</li>
|
||||||
|
<li>IP-Adresse</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-muted-foreground mt-2">
|
||||||
|
Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Die Erfassung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. f DSGVO.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Kontaktformular</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Wenn Sie uns per Kontaktformular Anfragen zukommen lassen, werden Ihre Angaben aus dem Anfrageformular inklusive der von Ihnen dort angegebenen Kontaktdaten zwecks Bearbeitung der Anfrage und für den Fall von Anschlussfragen bei uns gespeichert. Diese Daten geben wir nicht ohne Ihre Einwilligung weiter.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="mb-8">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>4. Analyse-Tools und Tools von Drittanbietern</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Google Analytics</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Diese Website nutzt Funktionen des Webanalysedienstes Google Analytics. Anbieter ist die Google Ireland Limited, Gordon House, Barrow Street, Dublin 4, Irland.
|
||||||
|
</p>
|
||||||
|
<p className="text-muted-foreground mt-2">
|
||||||
|
Google Analytics verwendet so genannte "Cookies". Das sind Textdateien, die auf Ihrem Computer gespeichert werden und die eine Analyse der Benutzung der Website durch Sie ermöglichen. Die durch das Cookie erzeugten Informationen über Ihre Benutzung dieser Website werden in der Regel an einen Server von Google in den USA übertragen und dort gespeichert.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="mb-8">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>5. Ihre Rechte</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Widerruf Ihrer Einwilligung zur Datenverarbeitung</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Viele Datenverarbeitungsvorgänge sind nur mit Ihrer ausdrücklichen Einwilligung möglich. Sie können eine bereits erteilte Einwilligung jederzeit widerrufen. Die Rechtmäßigkeit der bis zum Widerruf erfolgten Datenverarbeitung bleibt vom Widerruf unberührt.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Recht auf Datenübertragbarkeit</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Sie haben das Recht, Daten, die wir auf Grundlage Ihrer Einwilligung oder in Erfüllung eines Vertrags automatisiert verarbeiten, an sich oder an einen Dritten in einem gängigen, maschinenlesbaren Format aushändigen zu lassen. Sofern Sie die direkte Übertragung der Daten an einen anderen Verantwortlichen verlangen, erfolgt dies nur, soweit es technisch machbar ist.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">SSL- bzw. TLS-Verschlüsselung</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Diese Seite nutzt aus Sicherheitsgründen und zum Schutz der Übertragung vertraulicher Inhalte, wie zum Beispiel Bestellungen oder Anfragen, die Sie an uns als Seitenbetreiber senden, eine SSL- bzw. TLS-Verschlüsselung. Eine verschlüsselte Verbindung erkennen Sie daran, dass die Adresszeile des Browsers von "http://" auf "https://" wechselt und an dem Schloss-Symbol in Ihrer Browserzeile.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>6. Kontakt</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Bei Fragen zum Datenschutz können Sie uns über die auf dieser Website verfügbaren Kontaktmöglichkeiten erreichen.
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Datenschutz;
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import Header from "@/components/Header";
|
||||||
|
import Footer from "@/components/Footer";
|
||||||
|
|
||||||
|
const Impressum = () => {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-background">
|
||||||
|
<Header />
|
||||||
|
|
||||||
|
<div className="container mx-auto px-4 py-16 mt-16">
|
||||||
|
<div className="max-w-4xl mx-auto">
|
||||||
|
<h1 className="text-4xl font-bold text-foreground mb-8">Impressum</h1>
|
||||||
|
|
||||||
|
<Card className="mb-8">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Angaben gemäß § 5 TMG</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Betreiber dieser Website</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Diese Website wird von einem privaten Betreiber geführt.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Haftungsausschluss</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Die Inhalte dieser Website dienen der allgemeinen Information. Wir übernehmen keine Gewähr für die Vollständigkeit, Richtigkeit oder Aktualität der bereitgestellten Informationen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg mb-2">Urheberrecht</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Die Inhalte dieser Website unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Impressum;
|
||||||
|
|
@ -3,13 +3,17 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { SimpleSelect, SimpleSelectItem } from "@/components/ui/simple-select";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { Building2, MapPin, Phone, Mail, Globe, CheckCircle, Users, Award, Clock } from "lucide-react";
|
import { Building2, MapPin, Phone, Mail, Globe, CheckCircle, Users, Award, Clock } from "lucide-react";
|
||||||
import Header from "@/components/Header";
|
import Header from "@/components/Header";
|
||||||
|
import { usePostHog } from "@/hooks/usePostHog";
|
||||||
|
import { sendCompanyRegistrationEmail } from "@/lib/emailService";
|
||||||
|
|
||||||
const UnternehmenListen = () => {
|
const UnternehmenListen = () => {
|
||||||
|
const posthog = usePostHog();
|
||||||
|
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
companyName: "",
|
companyName: "",
|
||||||
contactPerson: "",
|
contactPerson: "",
|
||||||
|
|
@ -37,6 +41,14 @@ const UnternehmenListen = () => {
|
||||||
...prev,
|
...prev,
|
||||||
[field]: value
|
[field]: value
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Track form interactions
|
||||||
|
if (field === 'experience') {
|
||||||
|
posthog.capture('experience_selected', {
|
||||||
|
experience_level: value,
|
||||||
|
form_section: 'company_registration'
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEnergyTypeChange = (type: string, checked: boolean) => {
|
const handleEnergyTypeChange = (type: string, checked: boolean) => {
|
||||||
|
|
@ -51,6 +63,13 @@ const UnternehmenListen = () => {
|
||||||
energyTypes: prev.energyTypes.filter(t => t !== type)
|
energyTypes: prev.energyTypes.filter(t => t !== type)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track energy type selection
|
||||||
|
posthog.capture('energy_type_selected', {
|
||||||
|
energy_type: type,
|
||||||
|
selected: checked,
|
||||||
|
form_section: 'company_registration'
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleServiceChange = (service: string, checked: boolean) => {
|
const handleServiceChange = (service: string, checked: boolean) => {
|
||||||
|
|
@ -65,14 +84,63 @@ const UnternehmenListen = () => {
|
||||||
services: prev.services.filter(s => s !== service)
|
services: prev.services.filter(s => s !== service)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track service selection
|
||||||
|
posthog.capture('service_selected', {
|
||||||
|
service: service,
|
||||||
|
selected: checked,
|
||||||
|
form_section: 'company_registration'
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setIsSubmitting(true);
|
setIsSubmitting(true);
|
||||||
|
|
||||||
// Simulate API call
|
// Track form submission in PostHog
|
||||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
posthog.capture('company_registration_started', {
|
||||||
|
company_name: formData.companyName,
|
||||||
|
energy_types: formData.energyTypes,
|
||||||
|
services: formData.services,
|
||||||
|
experience: formData.experience,
|
||||||
|
location: `${formData.zipCode} ${formData.city}`
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Send email notification via webhook
|
||||||
|
const result = await sendCompanyRegistrationEmail(formData);
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
console.log('✅ E-Mail erfolgreich an Webhook gesendet!');
|
||||||
|
console.log('📧 Daten wurden an knuth.timo@gmail.com weitergeleitet');
|
||||||
|
|
||||||
|
// Track successful submission
|
||||||
|
posthog.capture('company_registration_completed', {
|
||||||
|
company_name: formData.companyName,
|
||||||
|
energy_types: formData.energyTypes,
|
||||||
|
services: formData.services,
|
||||||
|
experience: formData.experience,
|
||||||
|
location: `${formData.zipCode} ${formData.city}`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('⚠️ Webhook-Fehler, aber Daten wurden geloggt:', result.data);
|
||||||
|
|
||||||
|
// Track failed submission
|
||||||
|
posthog.capture('company_registration_failed', {
|
||||||
|
company_name: formData.companyName,
|
||||||
|
error: result.error || 'Webhook failed'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Fehler beim Senden der E-Mail:', error);
|
||||||
|
|
||||||
|
// Track failed submission
|
||||||
|
posthog.capture('company_registration_failed', {
|
||||||
|
company_name: formData.companyName,
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
setIsSubmitted(true);
|
setIsSubmitted(true);
|
||||||
|
|
@ -266,17 +334,16 @@ const UnternehmenListen = () => {
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="experience">Jahre Erfahrung *</Label>
|
<Label htmlFor="experience">Jahre Erfahrung *</Label>
|
||||||
<Select value={formData.experience} onValueChange={(value) => handleInputChange("experience", value)}>
|
<SimpleSelect
|
||||||
<SelectTrigger>
|
value={formData.experience}
|
||||||
<SelectValue placeholder="Erfahrung wählen" />
|
onValueChange={(value) => handleInputChange("experience", value)}
|
||||||
</SelectTrigger>
|
placeholder="Erfahrung wählen"
|
||||||
<SelectContent>
|
>
|
||||||
<SelectItem value="0-2">0-2 Jahre</SelectItem>
|
<SimpleSelectItem value="0-2">0-2 Jahre</SimpleSelectItem>
|
||||||
<SelectItem value="3-5">3-5 Jahre</SelectItem>
|
<SimpleSelectItem value="3-5">3-5 Jahre</SimpleSelectItem>
|
||||||
<SelectItem value="6-10">6-10 Jahre</SelectItem>
|
<SimpleSelectItem value="6-10">6-10 Jahre</SimpleSelectItem>
|
||||||
<SelectItem value="10+">Über 10 Jahre</SelectItem>
|
<SimpleSelectItem value="10+">Über 10 Jahre</SimpleSelectItem>
|
||||||
</SelectContent>
|
</SimpleSelect>
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="coverageArea">Einzugsgebiet</Label>
|
<Label htmlFor="coverageArea">Einzugsgebiet</Label>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue