# Reactions Feature Implementation & Troubleshooting

## Overview
This document covers the complete implementation and troubleshooting of the reactions feature in the Sojorn application, including both backend (Go) and frontend (Flutter) components.

## Problem Statement
The reactions feature had multiple issues:
1. **Backend 500 errors** when toggling reactions
2. **Frontend not showing reactions** on initial load (showing `null`)
3. **UI not updating immediately** after toggling reactions
4. **Need to refresh page** to see reaction changes

## Backend Issues & Solutions

### Issue 1: pgx.ErrNoRows vs sql.ErrNoRows
**Problem**: The Go backend was using `sql.ErrNoRows` to check for no rows in database queries, but pgx returns `pgx.ErrNoRows`.

**Error**: 
```
ERR DEBUG: Failed to check existing reaction - unexpected error error="no rows in result set"
```

**Solution**: Update error handling in `internal/repository/post_repository.go`:
```go
import (
    "github.com/jackc/pgx/v5"  // Add this import
)

// Change from:
} else if err != sql.ErrNoRows {

// To:
} else if err != pgx.ErrNoRows {
```

### Issue 2: JSON Serialization Omitting Empty Fields
**Problem**: The `Post` model had `omitempty` tags on reaction fields, causing them to be omitted from JSON responses when empty.

**Solution**: Remove `omitempty` from reaction JSON tags in `internal/models/post.go`:
```go
// Before:
Reactions        map[string]int    `json:"reactions,omitempty"`
MyReactions      []string          `json:"my_reactions,omitempty"`
ReactionUsers    map[string][]string `json:"reaction_users,omitempty"`

// After:
Reactions        map[string]int    `json:"reactions"`
MyReactions      []string          `json:"my_reactions"`
ReactionUsers    map[string][]string `json:"reaction_users"`
```

## Frontend Issues & Solutions

### Issue 1: UI Not Updating Immediately
**Problem**: The `_reactionCountsFor` and `_myReactionsFor` methods prioritized `post.reactions` over local state, but after toggle reactions, local state had updated data while `post.reactions` still had old data.

**Solution**: Change priority to prefer local state for immediate updates in `lib/screens/post/threaded_conversation_screen.dart`:

```dart
Map<String, int> _reactionCountsFor(Post post) {
  // Prefer local state for immediate updates after toggle reactions
  final localState = _reactionCountsByPost[post.id];
  if (localState != null) {
    return localState;
  }
  // Fall back to post model if no local state
  return post.reactions ?? {};
}

Set<String> _myReactionsFor(Post post) {
  // Prefer local state for immediate updates after toggle reactions
  final localState = _myReactionsByPost[post.id];
  if (localState != null) {
    return localState;
  }
  // Fall back to post model if no local state
  return post.myReactions?.toSet() ?? <String>{};
}
```

## Implementation Steps

### Backend Implementation
1. **Fix Error Handling**:
   ```bash
   cd go-backend
   # Edit internal/repository/post_repository.go
   # Add pgx import and change error handling
   git add . && git commit -m "Fix ToggleReaction error handling - use pgx.ErrNoRows"
   ```

2. **Fix JSON Serialization**:
   ```bash
   # Edit internal/models/post.go
   # Remove omitempty from reaction fields
   git add . && git commit -m "Remove omitempty from reaction JSON fields"
   ```

3. **Deploy Backend**:
   ```bash
   cd /opt/sojorn/go-backend
   git pull origin ThreadRestoration
   sudo systemctl stop sojorn-api
   go build -o ../bin/api ./cmd/api
   sudo systemctl start sojorn-api
   ```

### Frontend Implementation
1. **Fix UI Update Priority**:
   ```bash
   cd sojorn_app
   # Edit lib/screens/post/threaded_conversation_screen.dart
   # Update _reactionCountsFor and _myReactionsFor methods
   git add . && git commit -m "Fix reaction UI updates - prioritize local state"
   ```

## Debugging Techniques

### Backend Debugging
1. **Add Debug Logging**:
   ```go
   log.Info().Str("postID", postID).Str("userID", userID).Msg("DEBUG: No existing reaction found (expected)")
   log.Error().Err(err).Str("postID", postID).Str("userID", userID).Msg("DEBUG: Failed to check existing reaction - unexpected error")
   ```

2. **Monitor Logs**:
   ```bash
   sudo tail -f /var/log/syslog | grep api
   ```

### Frontend Debugging
1. **Add Debug Logging**:
   ```dart
   print('DEBUG: Toggle reaction response: $response');
   print('DEBUG: Updated local reaction counts: ${_reactionCountsByPost[postId]}');
   print('DEBUG: Using local state: ${localState}');
   ```

2. **Check API Response**:
   ```dart
   final response = await api.toggleReaction(postId, emoji);
   print('DEBUG: API response: $response');
   ```

## Testing Checklist

### Backend Tests
- [ ] Toggle reaction returns 200 (not 500)
- [ ] Reaction is saved to database
- [ ] API response includes updated counts and user reactions
- [ ] Empty reaction fields return `{}` and `[]` instead of `null`

### Frontend Tests
- [ ] Reactions show on initial load
- [ ] Toggle reaction updates UI immediately
- [ ] No refresh needed to see changes
- [ ] Selected emoji shows as selected
- [ ] Reaction count updates correctly

## Common Issues & Solutions

### Issue: "no rows in result set" Error
**Cause**: Using `sql.ErrNoRows` instead of `pgx.ErrNoRows`
**Fix**: Update error handling to use `pgx.ErrNoRows`

### Issue: Frontend Shows `null` for Reactions
**Cause**: `omitempty` in JSON tags omits empty fields
**Fix**: Remove `omitempty` from reaction field JSON tags

### Issue: UI Not Updating After Toggle
**Cause**: UI prioritizes old post data over updated local state
**Fix**: Change priority to prefer local state for immediate updates

### Issue: Need to Refresh to See Changes
**Cause**: Same as above - UI not using updated local state
**Fix**: Same solution - prioritize local state

## Key Files Modified

### Backend
- `internal/repository/post_repository.go` - Error handling fix
- `internal/models/post.go` - JSON serialization fix

### Frontend
- `lib/screens/post/threaded_conversation_screen.dart` - UI update priority fix

## Verification Commands

### Backend Verification
```bash
# Check if service is running
sudo systemctl status sojorn-api

# Check logs for errors
sudo tail -f /var/log/syslog | grep api

# Test API endpoint
curl -X POST "http://194.238.28.122:8080/api/v1/posts/{post-id}/reactions/toggle" \
  -H "Authorization: Bearer {jwt-token}" \
  -H "Content-Type: application/json" \
  -d '{"emoji": "❤️"}'
```

### Frontend Verification
```bash
# Check Flutter logs
flutter run --verbose

# Look for debug messages
grep "DEBUG:" flutter_logs.txt
```

## Success Criteria
✅ **Backend**: Toggle reactions return 200, no 500 errors
✅ **Frontend**: Reactions show immediately, no refresh needed
✅ **UI**: Selected emojis display correctly
✅ **Data**: Empty reactions show as empty, not null

## Future Improvements
1. **Optimistic Updates**: Implement proper optimistic UI updates
2. **Error Handling**: Better error messages for failed reactions
3. **Performance**: Cache reaction data to reduce API calls
4. **Real-time**: WebSocket updates for live reaction changes
