fix: add support for Clerk IDs and activity endpoint
- Update getUserProfile to accept both database ID and Clerk ID - Update getUserReports to handle Clerk IDs - Update getUserEvents to handle Clerk IDs - Add getUserActivity endpoint to return timeline of user actions - Add activity route GET /api/users/:id/activity - Fix TypeScript errors with const assertions This fixes 404 errors when frontend uses Clerk IDs to fetch user data
This commit is contained in:
@@ -56,11 +56,14 @@ export class UserService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user profile by database ID
|
||||
* Get user profile by database ID or Clerk ID
|
||||
*/
|
||||
async getUserProfile(userId: string) {
|
||||
// Check if this is a Clerk ID (starts with 'user_')
|
||||
const isClerkId = userId.startsWith('user_');
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
where: isClerkId ? { clerkId: userId } : { id: userId },
|
||||
select: {
|
||||
id: true,
|
||||
clerkId: true,
|
||||
@@ -142,11 +145,26 @@ export class UserService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's reports
|
||||
* Get user's reports by database ID or Clerk ID
|
||||
*/
|
||||
async getUserReports(userId: string) {
|
||||
// Check if this is a Clerk ID and convert to database ID
|
||||
const isClerkId = userId.startsWith('user_');
|
||||
let dbUserId = userId;
|
||||
|
||||
if (isClerkId) {
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { clerkId: userId },
|
||||
select: { id: true },
|
||||
});
|
||||
if (!user) {
|
||||
throw new Error('User not found');
|
||||
}
|
||||
dbUserId = user.id;
|
||||
}
|
||||
|
||||
const reports = await prisma.report.findMany({
|
||||
where: { userId },
|
||||
where: { userId: dbUserId },
|
||||
include: {
|
||||
environmentalConcerns: true,
|
||||
verifications: true,
|
||||
@@ -160,12 +178,27 @@ export class UserService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's events (both registered and organized)
|
||||
* Get user's events (both registered and organized) by database ID or Clerk ID
|
||||
*/
|
||||
async getUserEvents(userId: string) {
|
||||
// Check if this is a Clerk ID and convert to database ID
|
||||
const isClerkId = userId.startsWith('user_');
|
||||
let dbUserId = userId;
|
||||
|
||||
if (isClerkId) {
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { clerkId: userId },
|
||||
select: { id: true },
|
||||
});
|
||||
if (!user) {
|
||||
throw new Error('User not found');
|
||||
}
|
||||
dbUserId = user.id;
|
||||
}
|
||||
|
||||
// Get events user has registered for
|
||||
const registeredEvents = await prisma.eventRegistration.findMany({
|
||||
where: { userId },
|
||||
where: { userId: dbUserId },
|
||||
include: {
|
||||
event: {
|
||||
include: {
|
||||
@@ -186,7 +219,7 @@ export class UserService {
|
||||
|
||||
// Get events user has organized
|
||||
const organizedEvents = await prisma.event.findMany({
|
||||
where: { organizerId: userId },
|
||||
where: { organizerId: dbUserId },
|
||||
include: {
|
||||
organizer: {
|
||||
select: {
|
||||
@@ -237,6 +270,132 @@ export class UserService {
|
||||
return updatedUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's activity timeline
|
||||
*/
|
||||
async getUserActivity(userId: string) {
|
||||
// Check if this is a Clerk ID and convert to database ID
|
||||
const isClerkId = userId.startsWith('user_');
|
||||
let dbUserId = userId;
|
||||
|
||||
if (isClerkId) {
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { clerkId: userId },
|
||||
select: { id: true },
|
||||
});
|
||||
if (!user) {
|
||||
throw new Error('User not found');
|
||||
}
|
||||
dbUserId = user.id;
|
||||
}
|
||||
|
||||
// Get user's reports
|
||||
const reports = await prisma.report.findMany({
|
||||
where: { userId: dbUserId },
|
||||
select: {
|
||||
id: true,
|
||||
createdAt: true,
|
||||
litterType: true,
|
||||
quantity: true,
|
||||
latitude: true,
|
||||
longitude: true,
|
||||
description: true,
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 50,
|
||||
});
|
||||
|
||||
// Get user's event registrations
|
||||
const eventRegistrations = await prisma.eventRegistration.findMany({
|
||||
where: { userId: dbUserId },
|
||||
include: {
|
||||
event: {
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
description: true,
|
||||
scheduledDate: true,
|
||||
latitude: true,
|
||||
longitude: true,
|
||||
locationName: true,
|
||||
status: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: { registeredAt: 'desc' },
|
||||
take: 50,
|
||||
});
|
||||
|
||||
// Get user's organized events
|
||||
const organizedEvents = await prisma.event.findMany({
|
||||
where: { organizerId: dbUserId },
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
description: true,
|
||||
createdAt: true,
|
||||
scheduledDate: true,
|
||||
latitude: true,
|
||||
longitude: true,
|
||||
locationName: true,
|
||||
status: true,
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 50,
|
||||
});
|
||||
|
||||
// Combine and format activities
|
||||
const activities = [
|
||||
...reports.map(report => ({
|
||||
id: report.id,
|
||||
type: 'report' as const,
|
||||
timestamp: report.createdAt || new Date(),
|
||||
title: `Reported ${report.litterType} litter`,
|
||||
description: report.description || `${report.quantity} amount of ${report.litterType}`,
|
||||
location: {
|
||||
latitude: Number(report.latitude),
|
||||
longitude: Number(report.longitude),
|
||||
},
|
||||
})),
|
||||
...eventRegistrations.map(reg => {
|
||||
const activityType: 'event_attended' = 'event_attended';
|
||||
return {
|
||||
id: reg.event.id,
|
||||
type: activityType,
|
||||
timestamp: reg.registeredAt || new Date(),
|
||||
title: reg.event.title,
|
||||
description: reg.event.description,
|
||||
location: {
|
||||
latitude: Number(reg.event.latitude),
|
||||
longitude: Number(reg.event.longitude),
|
||||
locationName: reg.event.locationName,
|
||||
},
|
||||
};
|
||||
}),
|
||||
...organizedEvents.map(event => {
|
||||
const activityType: 'event_created' | 'event_completed' =
|
||||
event.status === 'completed' ? 'event_completed' : 'event_created';
|
||||
return {
|
||||
id: event.id,
|
||||
type: activityType,
|
||||
timestamp: event.createdAt || new Date(),
|
||||
title: event.title,
|
||||
description: event.description,
|
||||
location: {
|
||||
latitude: Number(event.latitude),
|
||||
longitude: Number(event.longitude),
|
||||
locationName: event.locationName,
|
||||
},
|
||||
};
|
||||
}),
|
||||
];
|
||||
|
||||
// Sort by timestamp descending
|
||||
activities.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
|
||||
|
||||
return activities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate and update user impact score
|
||||
* Impact score = (reports * 10) + (events attended * 20) + (events organized * 50)
|
||||
|
||||
Reference in New Issue
Block a user