# Event Feedback API

**Author**: Josh, Lead Backend Team  
**Last Updated**: 2025-12-11  
**Version**: v1.0

**Base URL**: `https://api.nexgate.com/api/v1`

**Short Description**: The Event Feedback API enables attendees to rate and review events after attendance. This API provides a simple 5-star rating system with optional comments, prevents duplicate feedback, ensures only attendees (non-organizers) can submit reviews, and allows anyone to view event feedback with pagination. The system supports escrow release decisions based on feedback quality and helps organizers improve future events.

**Hints**: 
- **One Feedback Per User**: Each user can only submit one feedback per event
- **Attendee Only**: Event organizers cannot review their own events
- **5-Star Rating**: Required rating from 1-5 stars
- **Optional Comments**: Text reviews up to 1000 characters
- **Public Viewing**: Anyone can view event feedback (paginated)
- **Chronological Order**: Newest feedback first
- **Escrow Integration**: Feedback may influence escrow release (future)
- **Simple Model**: Focus on rating quality over complex metrics

---

## Response Structure

### EventFeedbackResponse
```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "eventId": "770e8400-e29b-41d4-a716-446655440002",
  "eventTitle": "East African Tech Summit 2025",
  "userId": "660e8400-e29b-41d4-a716-446655440001",
  "userName": "johndoe",
  "rating": 5,
  "comment": "Amazing event! The speakers were excellent and the venue was perfect. Definitely attending next year!",
  "createdAt": "2025-12-18T10:30:45Z"
}
```

### Paginated Response
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Feedbacks retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "content": [
      {
        "id": "uuid",
        "eventId": "uuid",
        "eventTitle": "East African Tech Summit 2025",
        "userId": "uuid",
        "userName": "johndoe",
        "rating": 5,
        "comment": "Great event!",
        "createdAt": "2025-12-18T10:30:45Z"
      }
    ],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 20,
      "offset": 0
    },
    "totalElements": 145,
    "totalPages": 8,
    "last": false,
    "first": true,
    "numberOfElements": 20,
    "size": 20,
    "number": 0,
    "empty": false
  }
}
```

---

## Endpoints

## 1. Create Feedback
**Endpoint**: <span style="background-color: #007bff; color: white; padding: 4px 8px; border-radius: 4px;">POST</span> `/feedbacks/event/{eventId}`

**Access**: 🔒 Authenticated Users (Non-Organizers)

**Path Parameters**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| eventId | string (UUID) | Yes | Event identifier |

**Request Headers**:
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| Authorization | string | Yes | Bearer token |
| Content-Type | string | Yes | application/json |

**Request Body**:
```json
{
  "rating": 5,
  "comment": "Amazing event! The speakers were excellent and the venue was perfect. Definitely attending next year!"
}
```

**Request Parameters**:
| Parameter | Type | Required | Description | Validation |
|-----------|------|----------|-------------|------------|
| rating | integer | Yes | Star rating | Min: 1, Max: 5 |
| comment | string | No | Text review | Max: 1000 characters |

**Success Response**: Returns EventFeedbackResponse

**Success Response Message**: "Feedback submitted successfully"

**HTTP Status Code**: 201 CREATED

**Behavior**:
1. Validates user is authenticated
2. Validates event exists
3. Checks user is NOT the event organizer
4. Checks user hasn't already submitted feedback
5. Creates feedback record
6. Returns created feedback

**Validation Rules**:
- ✅ Rating must be 1-5 (integer)
- ✅ Comment optional, max 1000 chars
- ✅ One feedback per user per event
- ✅ Organizers cannot review own events
- ✅ Event must exist

**Standard Error Types**:
- `400 BAD_REQUEST`: Invalid rating (not 1-5)
- `401 UNAUTHORIZED`: Not authenticated
- `403 FORBIDDEN`: Organizer trying to review own event
- `404 NOT_FOUND`: Event not found
- `409 CONFLICT`: Already submitted feedback

**Error Response Examples**:

*Invalid Rating (400):*
```json
{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Rating must be at least 1",
  "action_time": "2025-12-11T10:30:45",
  "data": "Rating must be at least 1"
}
```

*Organizer Cannot Review (403):*
```json
{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Event organizers cannot submit feedback for their own events.",
  "action_time": "2025-12-11T10:30:45",
  "data": "Event organizers cannot submit feedback for their own events."
}
```

*Already Submitted (409):*
```json
{
  "success": false,
  "httpStatus": "CONFLICT",
  "message": "You have already provided feedback for this event",
  "action_time": "2025-12-11T10:30:45",
  "data": "You have already provided feedback for this event"
}
```

---

## 2. Get Event Feedbacks
**Endpoint**: <span style="background-color: #28a745; color: white; padding: 4px 8px; border-radius: 4px;">GET</span> `/feedbacks/event/{eventId}?page=0&size=20`

**Access**: 🔓 Public (No Authentication Required)

**Path Parameters**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| eventId | string (UUID) | Yes | Event identifier |

**Query Parameters**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| page | integer | No | Page number (0-indexed, default: 0) |
| size | integer | No | Items per page (default: 20) |

**Success Response**: Returns Spring Page object with EventFeedbackResponse items

**Success Response Message**: "Feedbacks retrieved successfully"

**HTTP Status Code**: 200 OK

**Behavior**:
- Returns paginated list of feedback
- Sorted by creation date (newest first)
- No authentication required (public access)
- Validates event exists

**Pagination Details**:
- Zero-indexed pages (0, 1, 2...)
- Default page size: 20
- Max page size: 100 (recommended)
- Includes total elements and pages

**Standard Error Types**:
- `404 NOT_FOUND`: Event not found

---

## Rating System

### Star Ratings (1-5)

| Rating | Meaning | Emoji | Description |
|--------|---------|-------|-------------|
| 5 ⭐⭐⭐⭐⭐ | Excellent | 😍 | Outstanding event, exceeded expectations |
| 4 ⭐⭐⭐⭐ | Very Good | 😊 | Great event, minor improvements possible |
| 3 ⭐⭐⭐ | Good | 🙂 | Satisfactory event, met expectations |
| 2 ⭐⭐ | Fair | 😐 | Below expectations, needs improvement |
| 1 ⭐ | Poor | 😞 | Disappointing event, significant issues |

### Average Rating Calculation

```
Average = Sum of all ratings / Number of feedbacks
```

**Example**:
```
Ratings: 5, 5, 4, 5, 3, 4, 5, 5, 4, 5
Total: 45
Count: 10
Average: 4.5 stars
```

**Display Format**: `4.5 ⭐ (10 reviews)`

---

## Comment Guidelines

### Recommended Comment Content

**Good Comments Include**:
- ✅ What you enjoyed
- ✅ Specific highlights (speakers, venue, activities)
- ✅ Suggestions for improvement
- ✅ Overall experience summary

**Example Good Comments**:
```
"Amazing event! The keynote speakers were excellent and provided valuable insights. 
The venue was perfect and well-organized. Only suggestion would be to have longer 
lunch breaks. Will definitely attend next year!"

"Great networking opportunities and diverse range of topics. Sound system could 
be improved in the main hall."

"Well organized but sessions felt rushed. Would prefer fewer sessions with more 
time for Q&A."
```

**Avoid**:
- ❌ Offensive language
- ❌ Personal attacks
- ❌ Spam or promotional content
- ❌ Off-topic comments

### Character Limit
- Maximum: **1000 characters**
- Recommended: 100-500 characters
- Minimum: None (optional field)

---

## Access Control

### Who Can Submit Feedback?

**Allowed**:
- ✅ Any authenticated user
- ✅ Attendees (purchased tickets)
- ✅ Non-attendees (also allowed currently)

**Not Allowed**:
- ❌ Event organizers (for their own events)
- ❌ Users who already submitted feedback
- ❌ Unauthenticated users

**Future Restriction** (Recommended):
- Only users who purchased tickets
- Requires checking booking history
- Prevents fake reviews

### Who Can View Feedback?

**Anyone** (Public access):
- ✅ No authentication required
- ✅ Potential attendees researching events
- ✅ Event organizers viewing their reviews
- ✅ Platform admins

---

## Use Cases

### Submit Feedback After Event
```
POST /feedbacks/event/{eventId}
{
  "rating": 5,
  "comment": "Great event, highly recommend!"
}

User provides honest review after attending
```

### View Event Reviews Before Booking
```
GET /feedbacks/event/{eventId}?page=0&size=20

Potential attendee checks reviews before purchasing tickets
Sees average rating and recent comments
```

### Organizer Checks Feedback
```
GET /feedbacks/event/{eventId}?page=0&size=20

Organizer views all feedback for their event
Identifies areas for improvement
Plans better future events
```

### Platform Quality Monitoring
```
GET /feedbacks/event/{eventId}?page=0&size=20

Platform admin reviews feedback
Identifies low-rated events
May influence escrow release decisions
```

---

## Future Enhancements

### Planned Features

**1. Verified Attendee Badge**
- Only show "Verified Attendee" if user has booking
- Increases trust in reviews
- Current: Anyone can review (not implemented)

**2. Average Rating Endpoint**
```
GET /feedbacks/event/{eventId}/summary
{
  "averageRating": 4.5,
  "totalReviews": 145,
  "ratingDistribution": {
    "5": 90,
    "4": 35,
    "3": 15,
    "2": 3,
    "1": 2
  }
}
```

**3. Helpful Votes**
- Users can mark reviews as helpful
- Sort by most helpful
- Bubble up quality reviews

**4. Organizer Response**
- Organizers can reply to feedback
- Shows engagement and care
- Builds trust with future attendees

**5. Escrow Integration**
- Average rating influences escrow release
- Events <3 stars may require manual review
- Automatic release for 4+ stars
- Current: Not implemented

---

## Escrow Release Logic (Future)

### How Feedback May Affect Escrow

**High Ratings** (4-5 stars average):
- ✅ Automatic escrow release
- Indicates successful event
- No manual review needed

**Medium Ratings** (3-3.9 stars average):
- ⚠️ Manual review triggered
- Platform checks for issues
- May contact organizer
- Usually released after review

**Low Ratings** (<3 stars average):
- ❌ Escrow release delayed
- Investigation required
- May require organizer explanation
- Possible refunds if serious issues

**Example**:
```
Event with 4.5 average rating (90% 5-star):
→ Escrow automatically released 24 hours after event

Event with 2.8 average rating (50% 1-2 star):
→ Escrow held, manual review, contact organizer
→ Possible partial refunds if issues confirmed
```

**Current Status**: Not implemented (all events release automatically)

---

## Best Practices

### For Attendees
✅ Submit honest, constructive feedback  
✅ Mention specific positives and negatives  
✅ Wait until after event to review  
✅ Be respectful in comments  
✅ Update review if organizer addresses issues (future)  

### For Organizers
✅ Read all feedback carefully  
✅ Identify patterns in complaints  
✅ Thank reviewers for positive feedback (future)  
✅ Address concerns in organizer response (future)  
✅ Use feedback to improve future events  

### For Platform
✅ Monitor feedback quality  
✅ Flag suspicious reviews  
✅ Use ratings in escrow decisions (future)  
✅ Display average ratings prominently  
✅ Encourage verified attendee reviews (future)  

---

## Quick Reference

### HTTP Status Codes
- `200 OK`: Feedbacks retrieved successfully
- `201 CREATED`: Feedback submitted successfully
- `400 BAD_REQUEST`: Invalid rating value
- `401 UNAUTHORIZED`: Not authenticated
- `403 FORBIDDEN`: Organizer reviewing own event
- `404 NOT_FOUND`: Event not found
- `409 CONFLICT`: Already submitted feedback

### Rating Range
- **Minimum**: 1 star (Poor)
- **Maximum**: 5 stars (Excellent)
- **Type**: Integer only (no half stars)

### Comment Length
- **Minimum**: 0 (optional)
- **Maximum**: 1000 characters
- **Recommended**: 100-500 characters

### Pagination
- **Default Page**: 0 (first page)
- **Default Size**: 20 items
- **Max Size**: 100 (recommended)
- **Sort Order**: Newest first (createdAt DESC)

### Data Formats
- **Event ID**: UUID format
- **User ID**: UUID format
- **Created At**: ISO 8601 timestamp (Instant)
- **Rating**: Integer (1-5)

---

## Integration Examples

### Submit Feedback Form
```javascript
const submitFeedback = async (eventId, rating, comment) => {
  const response = await fetch(`/api/v1/e-events/feedbacks/event/${eventId}`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ rating, comment })
  });
  
  if (response.status === 201) {
    alert('Thank you for your feedback!');
  } else if (response.status === 409) {
    alert('You have already reviewed this event');
  } else if (response.status === 403) {
    alert('Organizers cannot review their own events');
  }
};
```

### Display Feedback List
```javascript
const loadFeedback = async (eventId, page = 0) => {
  const response = await fetch(
    `/api/v1/e-events/feedbacks/event/${eventId}?page=${page}&size=20`
  );
  const data = await response.json();
  
  const feedbacks = data.data.content;
  const averageRating = calculateAverage(feedbacks);
  
  displayFeedbacks(feedbacks, averageRating);
};

const calculateAverage = (feedbacks) => {
  if (feedbacks.length === 0) return 0;
  const sum = feedbacks.reduce((acc, f) => acc + f.rating, 0);
  return (sum / feedbacks.length).toFixed(1);
};
```

### Star Rating Component
```javascript
const StarRating = ({ rating, onChange }) => {
  const stars = [1, 2, 3, 4, 5];
  
  return (
    <div className="star-rating">
      {stars.map(star => (
        <span
          key={star}
          className={star <= rating ? 'star filled' : 'star'}
          onClick={() => onChange(star)}
        >
          ⭐
        </span>
      ))}
    </div>
  );
};
```

---

## Conclusion

The Event Feedback API provides simple yet effective review system with:

✅ **5-Star Ratings**: Simple and universally understood  
✅ **Optional Comments**: Detailed written feedback  
✅ **One Per User**: Prevents spam and duplicate reviews  
✅ **Organizer Protection**: Can't review own events  
✅ **Public Access**: Anyone can view to inform decisions  
✅ **Pagination**: Handles large numbers of reviews  
✅ **Future Integration**: Ready for escrow release logic