# 28 — Campaign Feedback Form System

> **Status**: Deployed  
> **Date**: 2026-04-05  
> **Feedback URL**: `/em/feedback?e={base64email}&c={campaignId}&n={name}&sig={hmac}`

---

## Overview

In-app feedback collection system integrated with the Newsletter V2 campaign system. Each campaign can define custom questions (or use defaults). Users access the form via an HMAC-signed link in emails — no login required.

---

## Question Types

| Type | Renders As | JSON Example |
|------|-----------|--------------|
| `rating` | ⭐ 1–5 interactive stars with Arabic labels | `{"id":"quality","label":"جودة النتائج","type":"rating"}` |
| `text` | RTL textarea with placeholder | `{"id":"suggestion","label":"اقتراحاتك","type":"text","placeholder":"..."}` |
| `choice` | Radio buttons | `{"id":"reuse","label":"هل ستستخدمها مجدداً؟","type":"choice","options":["نعم","لا","ربما"]}` |

### Default Questions (when campaign has no custom questions)

```json
[
  {"id": "rating", "label": "هل كانت الخدمة مفيدة لك؟", "type": "rating"},
  {"id": "what_liked", "label": "ما الذي أعجبك أكثر في الخدمة؟", "type": "text", "placeholder": "مثلاً: سرعة التوليد، جودة المراجع..."},
  {"id": "what_to_improve", "label": "ما الذي تتمنى تحسينه؟", "type": "text", "placeholder": "مثلاً: إضافة مصادر أكثر..."},
  {"id": "comments", "label": "ملاحظات إضافية", "type": "text", "placeholder": "أي شيء آخر تود إخبارنا به..."}
]
```

---

## How to Use

### 1. Set custom questions on a campaign

Via SQL (or future admin UI):
```sql
UPDATE email_campaign SET feedback_questions = '[
  {"id":"rating","label":"كيف تقيّم جودة استخراج النص؟","type":"rating"},
  {"id":"accuracy","label":"هل كان النص دقيقاً؟","type":"choice","options":["دقيق جداً","جيد","يحتاج تحسين"]},
  {"id":"feedback","label":"ملاحظاتك","type":"text","placeholder":"أخبرنا المزيد..."}
]' WHERE id = X;
```

### 2. Include the feedback link in the email template

Use these placeholders in your campaign HTML body:
```html
<a href="https://shamra-academia.com/em/feedback?e={{email_b64}}&c={{campaign_id}}&n={{first_name}}&sig={{feedback_sig}}">
  شاركنا رأيك
</a>
```

The system auto-generates `{{email_b64}}`, `{{campaign_id}}`, `{{feedback_sig}}` per recipient during send.

### 3. View responses in the admin dashboard

Go to `/jim19ud83/newsletter` → Campaigns tab → click **Feedback** button on any campaign.

Shows: total responses, average rating, and a table with each response (user, stars, answers, date).

### 4. Query responses via API

```
GET /jim19ud83/newsletter/api/feedback/{campaignId}
```

Returns:
```json
{
  "success": true,
  "data": [{"email":"...", "rating":5, "whatLiked":"...", ...}],
  "averageRating": 4.2,
  "totalResponses": 7
}
```

---

## Example: Feedback for Different Services

### Related Work Service
```json
[
  {"id": "rating", "label": "هل كانت نتيجة الدراسة المرجعية مفيدة لبحثك؟", "type": "rating"},
  {"id": "what_liked", "label": "ما الذي أعجبك أكثر في الخدمة؟", "type": "text"},
  {"id": "what_to_improve", "label": "ما الذي تتمنى تحسينه؟", "type": "text"},
  {"id": "comments", "label": "ملاحظات إضافية", "type": "text"}
]
```

### OCR Service
```json
[
  {"id": "rating", "label": "كيف تقيّم جودة استخراج النص؟", "type": "rating"},
  {"id": "accuracy", "label": "هل كان النص المستخرج دقيقاً؟", "type": "choice", "options": ["دقيق جداً", "جيد مع أخطاء بسيطة", "يحتاج تحسين كبير"]},
  {"id": "language", "label": "ما لغة المستند الذي استخرجت منه النص؟", "type": "choice", "options": ["عربي", "إنجليزي", "مختلط"]},
  {"id": "feedback", "label": "ملاحظاتك", "type": "text"}
]
```

### Translation Service
```json
[
  {"id": "rating", "label": "كيف تقيّم جودة الترجمة؟", "type": "rating"},
  {"id": "natural", "label": "هل كانت الترجمة طبيعية وسلسة؟", "type": "choice", "options": ["نعم تماماً", "غالباً", "تحتاج تعديل"]},
  {"id": "use_again", "label": "هل ستستخدم الخدمة مجدداً؟", "type": "choice", "options": ["نعم بالتأكيد", "ربما", "لا"]},
  {"id": "feedback", "label": "ما الذي يمكننا تحسينه؟", "type": "text"}
]
```

### General Platform Satisfaction
```json
[
  {"id": "rating", "label": "ما تقييمك العام لشمرا أكاديميا؟", "type": "rating"},
  {"id": "favorite", "label": "ما هي أكثر خدمة تستخدمها؟", "type": "choice", "options": ["البحث", "تحميل الرسائل", "الذكاء الصنعي", "المكتبة المرجعية", "OCR"]},
  {"id": "recommend", "label": "هل تنصح زملاءك باستخدام شمرا؟", "type": "choice", "options": ["نعم بالتأكيد", "ربما", "لا"]},
  {"id": "missing", "label": "ما الميزة التي تتمنى إضافتها؟", "type": "text"}
]
```

---

## Architecture

### Database

| Table | Purpose |
|-------|---------|
| `campaign_feedback` | Stores all responses (rating, text fields, JSON answers) |
| `email_campaign.feedback_questions` | JSON column defining custom questions per campaign |

### Files

```
src/Entity/CampaignFeedback.php          — Feedback entity (rating + answers JSON)
src/Repository/CampaignFeedbackRepository.php — findByCampaign, getAverageRating
src/Controller/CampaignFeedbackController.php — Public form (GET/POST), HMAC-verified
templates/newsletter_v2/feedback.html.twig    — Dynamic RTL form (stars, text, choice)
templates/newsletter_v2/feedback_campaign.html — Email template for feedback requests
migrations/Version20260405100000.php          — campaign_feedback table + feedback_questions column
```

### Security

- Form URL is HMAC-signed (`feedback` action) — unforgeable
- No login required — works from email click
- IP address logged for abuse prevention
- First `rating` type question is stored in the dedicated `rating` column for quick aggregation

### Email Placeholders

| Placeholder | Purpose |
|-------------|---------|
| `{{email_b64}}` | Base64-encoded recipient email |
| `{{campaign_id}}` | Campaign ID |
| `{{feedback_sig}}` | HMAC signature for `email:feedback` |
| `{{first_name}}` | Recipient first name |

---

## Migration

```
Version20260405100000
- CREATE TABLE campaign_feedback (id, campaign_id, user_id, email, first_name, rating, what_liked, what_to_improve, additional_comments, answers JSON, ip_address, created_at)
- ALTER TABLE email_campaign ADD feedback_questions JSON DEFAULT NULL
```
