- Add GET /api/users/:id for profile retrieval with stats - Add PATCH /api/users/:id for profile updates - Add GET /api/users/:id/reports to fetch user's reports - Add GET /api/users/:id/events to fetch user's events (registered & organized) - Add PATCH /api/users/:id/preferences for notification settings - Add POST /api/users/:id/calculate-impact for impact score calculation - Create userService with all business logic - Create userController with request handling - Create userRoutes and register in main server - Update frontend userService with new endpoints - Add comprehensive documentation in USER_PROFILE_ENDPOINTS.md - Add test script for manual endpoint testing Requirements satisfied: 6.3, 6.4, 6.5, 10.4
8.6 KiB
User Profile Endpoints Documentation
This document describes the user profile API endpoints implemented for the Beach Litter Mapping Platform.
Overview
The user profile endpoints provide functionality for:
- Retrieving user profiles with statistics
- Updating user profile information
- Managing notification preferences
- Fetching user's reports and events
- Calculating impact scores
Authentication
Most endpoints require authentication via Clerk session token:
Authorization: Bearer <clerk_session_token>
Endpoints
1. Get User Profile
Endpoint: GET /api/users/:id
Description: Retrieve a user's profile including statistics about their contributions.
Authentication: Not required (public profiles)
Parameters:
id(path) - User database ID
Response:
{
"id": "uuid",
"clerkId": "user_xxx",
"email": "user@example.com",
"username": "johndoe",
"firstName": "John",
"lastName": "Doe",
"avatarUrl": "https://...",
"impactScore": 150,
"notificationEmail": true,
"notificationInApp": true,
"areasOfInterest": [
{
"lat": 53.3498,
"lng": -6.2603,
"radius": 10
}
],
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z",
"stats": {
"reportsSubmitted": 5,
"eventsAttended": 3,
"eventsOrganized": 1
}
}
Error Responses:
404- User not found500- Internal server error
2. Update User Profile
Endpoint: PATCH /api/users/:id
Description: Update user profile information (first name, last name, username).
Authentication: Required (users can only update their own profile)
Parameters:
id(path) - User database ID
Request Body:
{
"firstName": "John",
"lastName": "Doe",
"username": "johndoe123"
}
All fields are optional. Only provided fields will be updated.
Response:
{
"id": "uuid",
"clerkId": "user_xxx",
"email": "user@example.com",
"username": "johndoe123",
"firstName": "John",
"lastName": "Doe",
"avatarUrl": "https://...",
"impactScore": 150,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
Error Responses:
400- Username already taken401- Not authenticated403- Cannot update another user's profile404- User not found500- Internal server error
3. Get User Reports
Endpoint: GET /api/users/:id/reports
Description: Retrieve all reports submitted by a user.
Authentication: Not required
Parameters:
id(path) - User database ID
Response:
[
{
"id": "uuid",
"userId": "uuid",
"latitude": 53.3498,
"longitude": -6.2603,
"locationSource": "gps",
"photoUrls": ["/uploads/photo1.jpg"],
"photoTimestamp": "2024-01-01T12:00:00.000Z",
"litterType": "plastic",
"quantity": "moderate",
"description": "Plastic bottles on beach",
"verificationStatus": "verified",
"createdAt": "2024-01-01T12:00:00.000Z",
"environmentalConcerns": [],
"verifications": []
}
]
Error Responses:
500- Internal server error
4. Get User Events
Endpoint: GET /api/users/:id/events
Description: Retrieve events the user has registered for and organized.
Authentication: Not required
Parameters:
id(path) - User database ID
Response:
{
"registered": [
{
"id": "uuid",
"title": "Beach Cleanup",
"description": "Community cleanup event",
"latitude": 53.3498,
"longitude": -6.2603,
"locationName": "Sandymount Beach",
"scheduledDate": "2024-02-01T10:00:00.000Z",
"duration": 120,
"status": "upcoming",
"participantCount": 15,
"organizer": {
"id": "uuid",
"username": "organizer",
"avatarUrl": "https://..."
},
"registeredAt": "2024-01-15T10:00:00.000Z",
"attended": false
}
],
"organized": [
{
"id": "uuid",
"title": "My Beach Cleanup",
"description": "Event I organized",
"latitude": 53.3498,
"longitude": -6.2603,
"locationName": "Dollymount Beach",
"scheduledDate": "2024-03-01T10:00:00.000Z",
"duration": 180,
"status": "upcoming",
"participantCount": 20,
"organizer": {
"id": "uuid",
"username": "johndoe",
"avatarUrl": "https://..."
},
"registrations": []
}
]
}
Error Responses:
500- Internal server error
5. Update Notification Preferences
Endpoint: PATCH /api/users/:id/preferences
Description: Update user's notification preferences and areas of interest.
Authentication: Required (users can only update their own preferences)
Parameters:
id(path) - User database ID
Request Body:
{
"notificationEmail": true,
"notificationInApp": true,
"areasOfInterest": [
{
"lat": 53.3498,
"lng": -6.2603,
"radius": 10
},
{
"lat": 51.8985,
"lng": -8.4756,
"radius": 25
}
]
}
Field Validation:
radiusmust be between 1 and 50 kilometers- Each area must have
lat,lng, andradius
Response:
{
"id": "uuid",
"notificationEmail": true,
"notificationInApp": true,
"areasOfInterest": [
{
"lat": 53.3498,
"lng": -6.2603,
"radius": 10
}
]
}
Error Responses:
400- Validation error (invalid radius, missing fields, etc.)401- Not authenticated403- Cannot update another user's preferences404- User not found500- Internal server error
6. Calculate Impact Score
Endpoint: POST /api/users/:id/calculate-impact
Description: Calculate and update the user's impact score based on their contributions.
Authentication: Not required
Parameters:
id(path) - User database ID
Impact Score Formula:
Impact Score = (reports × 10) + (events attended × 20) + (events organized × 50)
Response:
{
"impactScore": 150
}
Error Responses:
404- User not found500- Internal server error
Usage Examples
Get User Profile
curl http://localhost:3005/api/users/abc-123
Update Profile
curl -X PATCH http://localhost:3005/api/users/abc-123 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"firstName": "John",
"lastName": "Doe",
"username": "johndoe"
}'
Update Notification Preferences
curl -X PATCH http://localhost:3005/api/users/abc-123/preferences \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"notificationEmail": true,
"notificationInApp": true,
"areasOfInterest": [
{
"lat": 53.3498,
"lng": -6.2603,
"radius": 10
}
]
}'
Calculate Impact Score
curl -X POST http://localhost:3005/api/users/abc-123/calculate-impact
Frontend Integration
The frontend service (src/services/userService.ts) provides TypeScript methods for all endpoints:
import { userService } from '@/services/userService';
// Get profile
const profile = await userService.getProfile(userId);
// Update profile
const updated = await userService.updateProfile(userId, {
firstName: 'John',
lastName: 'Doe',
username: 'johndoe'
});
// Get user's reports
const reports = await userService.getUserReports(userId);
// Get user's events
const events = await userService.getUserEvents(userId);
// Update notification preferences
const preferences = await userService.updateNotificationPreferences(userId, {
notificationEmail: true,
notificationInApp: true,
areasOfInterest: [
{ lat: 53.3498, lng: -6.2603, radius: 10 }
]
});
// Calculate impact score
const { impactScore } = await userService.calculateImpactScore(userId);
Requirements Satisfied
This implementation satisfies the following requirements from the specification:
- Requirement 6.3: User profile display showing submitted reports and events attended
- Requirement 6.4: Impact score calculation based on contributions
- Requirement 6.5: User profile showing map of submitted report locations (data provided via reports endpoint)
- Requirement 10.4: Notification preferences with area of interest configuration (1-50km radius)
Notes
- User authentication is handled by Clerk
- Users are automatically created in the database when they first interact with the API
- The
areasOfInterestfield is stored as JSON in the database - Impact scores are calculated on-demand but can be cached for performance
- All endpoints follow RESTful conventions
- Error responses follow a consistent format with error codes and timestamps