update deploy
This commit is contained in:
293
prompts/frontend-leads.md
Normal file
293
prompts/frontend-leads.md
Normal file
@@ -0,0 +1,293 @@
|
||||
# Frontend (Next.js) — Lead Form Entegrasyonu
|
||||
|
||||
## API Endpoint
|
||||
|
||||
```
|
||||
POST /api/v1/leads
|
||||
```
|
||||
|
||||
Auth yok, public endpoint. Rate limited.
|
||||
|
||||
---
|
||||
|
||||
## Request Body
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Ad Soyad",
|
||||
"phone": "+90 532 724 15 32",
|
||||
"email": "ornek@email.com",
|
||||
"source": "kurs_kayit",
|
||||
"target_course": "gemici-birlesik-egitimi",
|
||||
"education_level": "lise",
|
||||
"subject": "Eğitim başvurusu",
|
||||
"message": "Bilgi almak istiyorum",
|
||||
"kvkk_consent": true,
|
||||
"marketing_consent": false,
|
||||
"utm_source": "google",
|
||||
"utm_medium": "cpc",
|
||||
"utm_campaign": "denizcilik-2026"
|
||||
}
|
||||
```
|
||||
|
||||
### Zorunlu Alanlar
|
||||
| Alan | Tip | Açıklama |
|
||||
|------|-----|----------|
|
||||
| `name` | string | Ad Soyad (max 255) |
|
||||
| `phone` | string | Telefon (max 20) |
|
||||
| `source` | string | Form kaynağı (aşağıya bak) |
|
||||
| `kvkk_consent` | boolean | **Zorunlu, `true` olmalı** — checkbox onaylatılmalı |
|
||||
|
||||
### Opsiyonel Alanlar
|
||||
| Alan | Tip | Açıklama |
|
||||
|------|-----|----------|
|
||||
| `email` | string | E-posta |
|
||||
| `target_course` | string | Hedef eğitim slug'ı |
|
||||
| `education_level` | string | Eğitim seviyesi |
|
||||
| `subject` | string | Konu |
|
||||
| `message` | string | Mesaj |
|
||||
| `marketing_consent` | boolean | Pazarlama onayı |
|
||||
| `utm_source` | string | Google Analytics UTM |
|
||||
| `utm_medium` | string | — |
|
||||
| `utm_campaign` | string | — |
|
||||
|
||||
---
|
||||
|
||||
## Source Değerleri (Form Bazlı)
|
||||
|
||||
Her form kendi `source` değerini gönderir:
|
||||
|
||||
| Form | source | Zorunlu Alanlar | Opsiyonel Alanlar |
|
||||
|------|--------|-----------------|-------------------|
|
||||
| Kurs ön kayıt | `kurs_kayit` | name, phone, kvkk_consent | email, target_course, education_level, message |
|
||||
| Danışmanlık | `danismanlik` | name, phone, kvkk_consent | email, message, target_course |
|
||||
| Duyuru sidebar | `duyuru` | name, phone, kvkk_consent | email |
|
||||
| İletişim | `iletisim` | name, phone, kvkk_consent | email, subject, message |
|
||||
| Hero form | `hero_form` | name, phone, kvkk_consent | target_course |
|
||||
| WhatsApp widget | `whatsapp_widget` | name, phone, kvkk_consent | — |
|
||||
|
||||
---
|
||||
|
||||
## Response
|
||||
|
||||
### Başarılı (201):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Talebiniz alınmıştır. En kısa sürede sizinle iletişime geçeceğiz."
|
||||
}
|
||||
```
|
||||
|
||||
### Validasyon Hatası (422):
|
||||
```json
|
||||
{
|
||||
"message": "KVKK metnini onaylamanız gerekmektedir.",
|
||||
"errors": {
|
||||
"kvkk_consent": ["KVKK metnini onaylamanız gerekmektedir."],
|
||||
"name": ["Ad Soyad zorunludur."]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Form Örnekleri
|
||||
|
||||
### 1. Kurs Ön Kayıt Formu (Eğitim Detay Sayfası)
|
||||
|
||||
```tsx
|
||||
async function submitKursKayit(formData: FormData, courseSlug: string) {
|
||||
const utm = getUTMParams(); // URL'den utm_source, utm_medium, utm_campaign
|
||||
|
||||
const res = await fetch(`${API_URL}/api/v1/leads`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
name: formData.get('name'),
|
||||
phone: formData.get('phone'),
|
||||
email: formData.get('email') || undefined,
|
||||
source: 'kurs_kayit',
|
||||
target_course: courseSlug,
|
||||
education_level: formData.get('education_level') || undefined,
|
||||
message: formData.get('message') || undefined,
|
||||
kvkk_consent: formData.get('kvkk') === 'on',
|
||||
marketing_consent: formData.get('marketing') === 'on',
|
||||
...utm,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const err = await res.json();
|
||||
throw new Error(err.message);
|
||||
}
|
||||
return res.json();
|
||||
}
|
||||
```
|
||||
|
||||
Form alanları:
|
||||
- Ad Soyad (zorunlu)
|
||||
- Telefon (zorunlu)
|
||||
- E-posta
|
||||
- Eğitim Seviyesi (select: ilkokul, ortaokul, lise, onlisans, lisans)
|
||||
- Mesaj
|
||||
- [x] KVKK metnini okudum ve onaylıyorum (zorunlu checkbox)
|
||||
- [ ] Kampanya ve duyurulardan haberdar olmak istiyorum
|
||||
|
||||
### 2. Danışmanlık Formu
|
||||
|
||||
```tsx
|
||||
body: JSON.stringify({
|
||||
name: formData.get('name'),
|
||||
phone: formData.get('phone'),
|
||||
email: formData.get('email') || undefined,
|
||||
source: 'danismanlik',
|
||||
target_course: formData.get('interested_course') || undefined,
|
||||
message: formData.get('message') || undefined,
|
||||
kvkk_consent: true,
|
||||
...utm,
|
||||
})
|
||||
```
|
||||
|
||||
### 3. İletişim Formu
|
||||
|
||||
```tsx
|
||||
body: JSON.stringify({
|
||||
name: formData.get('name'),
|
||||
phone: formData.get('phone'),
|
||||
email: formData.get('email') || undefined,
|
||||
source: 'iletisim',
|
||||
subject: formData.get('subject') || undefined,
|
||||
message: formData.get('message'),
|
||||
kvkk_consent: true,
|
||||
...utm,
|
||||
})
|
||||
```
|
||||
|
||||
### 4. Duyuru Sidebar Mini Form
|
||||
|
||||
```tsx
|
||||
body: JSON.stringify({
|
||||
name: formData.get('name'),
|
||||
phone: formData.get('phone'),
|
||||
source: 'duyuru',
|
||||
kvkk_consent: true,
|
||||
...utm,
|
||||
})
|
||||
```
|
||||
|
||||
### 5. Hero Form (Anasayfa)
|
||||
|
||||
```tsx
|
||||
body: JSON.stringify({
|
||||
name: formData.get('name'),
|
||||
phone: formData.get('phone'),
|
||||
source: 'hero_form',
|
||||
target_course: formData.get('course') || undefined,
|
||||
kvkk_consent: true,
|
||||
...utm,
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## UTM Parametreleri
|
||||
|
||||
URL'deki UTM parametrelerini otomatik olarak form submit'e ekle:
|
||||
|
||||
```tsx
|
||||
function getUTMParams(): Record<string, string> {
|
||||
if (typeof window === 'undefined') return {};
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const utm: Record<string, string> = {};
|
||||
|
||||
for (const key of ['utm_source', 'utm_medium', 'utm_campaign']) {
|
||||
const val = params.get(key);
|
||||
if (val) utm[key] = val;
|
||||
}
|
||||
return utm;
|
||||
}
|
||||
```
|
||||
|
||||
UTM değerleri sayfa boyunca korunmalı (cookie veya sessionStorage):
|
||||
|
||||
```tsx
|
||||
// Sayfa ilk yüklendiğinde
|
||||
useEffect(() => {
|
||||
const utm = getUTMParams();
|
||||
if (Object.keys(utm).length > 0) {
|
||||
sessionStorage.setItem('utm', JSON.stringify(utm));
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Form submit'te
|
||||
const utm = JSON.parse(sessionStorage.getItem('utm') || '{}');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## KVKK Checkbox
|
||||
|
||||
Her formda KVKK onay checkbox'ı **zorunlu**. Backend `kvkk_consent: true` olmadan kabul etmez.
|
||||
|
||||
```tsx
|
||||
<label className="flex items-start gap-2">
|
||||
<input type="checkbox" name="kvkk" required />
|
||||
<span className="text-sm text-gray-600">
|
||||
<a href="/kvkk" target="_blank" className="underline">
|
||||
KVKK Aydınlatma Metni
|
||||
</a>'ni okudum ve onaylıyorum.
|
||||
</span>
|
||||
</label>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
```tsx
|
||||
try {
|
||||
const result = await submitLead(formData);
|
||||
// Başarılı — toast göster
|
||||
toast.success(result.message);
|
||||
form.reset();
|
||||
} catch (error) {
|
||||
if (error.status === 422) {
|
||||
// Validasyon hataları — form alanlarının altında göster
|
||||
const { errors } = await error.json();
|
||||
setFieldErrors(errors);
|
||||
} else if (error.status === 429) {
|
||||
// Rate limit — çok fazla istek
|
||||
toast.error('Çok fazla istek gönderildi. Lütfen biraz bekleyin.');
|
||||
} else {
|
||||
toast.error('Bir hata oluştu. Lütfen tekrar deneyin.');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## TypeScript Tipi
|
||||
|
||||
```ts
|
||||
interface LeadFormData {
|
||||
name: string;
|
||||
phone: string;
|
||||
email?: string;
|
||||
source: 'kurs_kayit' | 'danismanlik' | 'duyuru' | 'iletisim' | 'hero_form' | 'whatsapp_widget';
|
||||
target_course?: string;
|
||||
education_level?: string;
|
||||
subject?: string;
|
||||
message?: string;
|
||||
kvkk_consent: true; // Her zaman true olmalı
|
||||
marketing_consent?: boolean;
|
||||
utm_source?: string;
|
||||
utm_medium?: string;
|
||||
utm_campaign?: string;
|
||||
}
|
||||
|
||||
interface LeadResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user