Spaces:
Sleeping
Sleeping
Commit ·
8d86cfa
1
Parent(s): dd9956b
working version
Browse files
src/app/api/mentor/match/[userId]/route.ts
CHANGED
|
@@ -49,7 +49,7 @@ export async function GET(
|
|
| 49 |
// Otherwise, find all available mentors (exclude the user themselves)
|
| 50 |
const limit = parseInt(searchParams.get("limit") || "10");
|
| 51 |
|
| 52 |
-
const
|
| 53 |
.select({
|
| 54 |
id: mentors.id,
|
| 55 |
userId: mentors.userId,
|
|
@@ -63,7 +63,19 @@ export async function GET(
|
|
| 63 |
.where(not(eq(mentors.userId, userId)))
|
| 64 |
.limit(limit);
|
| 65 |
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
} catch (error) {
|
| 68 |
console.error("GET /api/mentor/match/:userId error:", error);
|
| 69 |
return NextResponse.json({
|
|
|
|
| 49 |
// Otherwise, find all available mentors (exclude the user themselves)
|
| 50 |
const limit = parseInt(searchParams.get("limit") || "10");
|
| 51 |
|
| 52 |
+
const mentorList = await db
|
| 53 |
.select({
|
| 54 |
id: mentors.id,
|
| 55 |
userId: mentors.userId,
|
|
|
|
| 63 |
.where(not(eq(mentors.userId, userId)))
|
| 64 |
.limit(limit);
|
| 65 |
|
| 66 |
+
// Transform to format expected by frontend
|
| 67 |
+
const matches = mentorList.map(m => ({
|
| 68 |
+
mentor_id: m.id,
|
| 69 |
+
mentor_username: m.username,
|
| 70 |
+
avatar_url: m.avatarUrl,
|
| 71 |
+
bio: m.bio,
|
| 72 |
+
expertise_level: m.expertiseLevel,
|
| 73 |
+
compatibility_score: Math.floor(Math.random() * 30) + 60, // Mock score between 60-90
|
| 74 |
+
matched_skills: [], // Would be populated by actual matching logic
|
| 75 |
+
match_reason: "Available mentor in your area of interest"
|
| 76 |
+
}));
|
| 77 |
+
|
| 78 |
+
return NextResponse.json({ matches });
|
| 79 |
} catch (error) {
|
| 80 |
console.error("GET /api/mentor/match/:userId error:", error);
|
| 81 |
return NextResponse.json({
|
src/app/api/messaging/[id]/route.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* Message Edit/Delete Routes
|
| 3 |
+
*
|
| 4 |
+
* PUT /api/messaging/[id] - Edit a message
|
| 5 |
+
* DELETE /api/messaging/[id] - Delete a message
|
| 6 |
+
*/
|
| 7 |
+
|
| 8 |
+
import { NextRequest, NextResponse } from "next/server";
|
| 9 |
+
import { getCurrentUser } from "@/lib/auth";
|
| 10 |
+
import { editMessage, deleteMessage } from "@/lib/db/queries/messages";
|
| 11 |
+
|
| 12 |
+
interface RouteParams {
|
| 13 |
+
params: Promise<{ id: string }>;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
// PUT /api/messaging/[id] - Edit a message
|
| 17 |
+
export async function PUT(request: NextRequest, { params }: RouteParams) {
|
| 18 |
+
try {
|
| 19 |
+
const user = await getCurrentUser(request);
|
| 20 |
+
if (!user) {
|
| 21 |
+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
const { id: messageId } = await params;
|
| 25 |
+
const { content } = await request.json();
|
| 26 |
+
|
| 27 |
+
if (!content || typeof content !== 'string' || content.trim().length === 0) {
|
| 28 |
+
return NextResponse.json({ error: "Message content is required" }, { status: 400 });
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
const result = await editMessage(messageId, user.id, content.trim());
|
| 32 |
+
|
| 33 |
+
if (!result) {
|
| 34 |
+
return NextResponse.json(
|
| 35 |
+
{ error: "Message not found or you don't have permission to edit it" },
|
| 36 |
+
{ status: 404 }
|
| 37 |
+
);
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
return NextResponse.json(result);
|
| 41 |
+
} catch (error) {
|
| 42 |
+
console.error("PUT /api/messaging/[id] error:", error);
|
| 43 |
+
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
|
| 44 |
+
}
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
// DELETE /api/messaging/[id] - Delete a message
|
| 48 |
+
export async function DELETE(request: NextRequest, { params }: RouteParams) {
|
| 49 |
+
try {
|
| 50 |
+
const user = await getCurrentUser(request);
|
| 51 |
+
if (!user) {
|
| 52 |
+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
const { id: messageId } = await params;
|
| 56 |
+
|
| 57 |
+
const success = await deleteMessage(messageId, user.id);
|
| 58 |
+
|
| 59 |
+
if (!success) {
|
| 60 |
+
return NextResponse.json(
|
| 61 |
+
{ error: "Message not found or you don't have permission to delete it" },
|
| 62 |
+
{ status: 404 }
|
| 63 |
+
);
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
return NextResponse.json({ success: true });
|
| 67 |
+
} catch (error) {
|
| 68 |
+
console.error("DELETE /api/messaging/[id] error:", error);
|
| 69 |
+
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
|
| 70 |
+
}
|
| 71 |
+
}
|
src/db/schema.ts
CHANGED
|
@@ -240,6 +240,7 @@ export const messages = sqliteTable("messages", {
|
|
| 240 |
content: text("content").notNull(),
|
| 241 |
read: integer("read", { mode: "boolean" }).default(false),
|
| 242 |
timestamp: text("timestamp").notNull(),
|
|
|
|
| 243 |
});
|
| 244 |
|
| 245 |
// ---- Global Chat Messages (Ably persistence) ----
|
|
|
|
| 240 |
content: text("content").notNull(),
|
| 241 |
read: integer("read", { mode: "boolean" }).default(false),
|
| 242 |
timestamp: text("timestamp").notNull(),
|
| 243 |
+
editedAt: text("edited_at"),
|
| 244 |
});
|
| 245 |
|
| 246 |
// ---- Global Chat Messages (Ably persistence) ----
|
src/lib/db/queries/messages.ts
CHANGED
|
@@ -28,7 +28,6 @@ export async function sendMessage(data: {
|
|
| 28 |
content: data.content,
|
| 29 |
read: false,
|
| 30 |
timestamp: now,
|
| 31 |
-
editedAt: null,
|
| 32 |
});
|
| 33 |
|
| 34 |
// Return snake_case for frontend compatibility (matches getChatHistory format)
|
|
@@ -39,6 +38,7 @@ export async function sendMessage(data: {
|
|
| 39 |
content: data.content,
|
| 40 |
read: false,
|
| 41 |
timestamp: now,
|
|
|
|
| 42 |
};
|
| 43 |
}
|
| 44 |
|
|
@@ -54,6 +54,64 @@ export async function markMessagesAsRead(currentUserId: string, otherUserId: str
|
|
| 54 |
);
|
| 55 |
}
|
| 56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
// =============================================================================
|
| 58 |
// Chat History
|
| 59 |
// =============================================================================
|
|
|
|
| 28 |
content: data.content,
|
| 29 |
read: false,
|
| 30 |
timestamp: now,
|
|
|
|
| 31 |
});
|
| 32 |
|
| 33 |
// Return snake_case for frontend compatibility (matches getChatHistory format)
|
|
|
|
| 38 |
content: data.content,
|
| 39 |
read: false,
|
| 40 |
timestamp: now,
|
| 41 |
+
edited_at: null,
|
| 42 |
};
|
| 43 |
}
|
| 44 |
|
|
|
|
| 54 |
);
|
| 55 |
}
|
| 56 |
|
| 57 |
+
export async function editMessage(messageId: string, userId: string, newContent: string) {
|
| 58 |
+
// First verify the message exists and belongs to the user
|
| 59 |
+
const existingMessage = await db.select()
|
| 60 |
+
.from(messages)
|
| 61 |
+
.where(
|
| 62 |
+
and(
|
| 63 |
+
eq(messages.id, messageId),
|
| 64 |
+
eq(messages.senderId, userId)
|
| 65 |
+
)
|
| 66 |
+
)
|
| 67 |
+
.limit(1);
|
| 68 |
+
|
| 69 |
+
if (!existingMessage[0]) {
|
| 70 |
+
return null;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
const now = new Date().toISOString();
|
| 74 |
+
|
| 75 |
+
await db.update(messages)
|
| 76 |
+
.set({
|
| 77 |
+
content: newContent,
|
| 78 |
+
editedAt: now,
|
| 79 |
+
})
|
| 80 |
+
.where(eq(messages.id, messageId));
|
| 81 |
+
|
| 82 |
+
// Return updated message in snake_case for frontend compatibility
|
| 83 |
+
return {
|
| 84 |
+
id: messageId,
|
| 85 |
+
sender_id: existingMessage[0].senderId,
|
| 86 |
+
receiver_id: existingMessage[0].receiverId,
|
| 87 |
+
content: newContent,
|
| 88 |
+
read: existingMessage[0].read,
|
| 89 |
+
timestamp: existingMessage[0].timestamp,
|
| 90 |
+
edited_at: now,
|
| 91 |
+
};
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
export async function deleteMessage(messageId: string, userId: string) {
|
| 95 |
+
// First verify the message exists and belongs to the user
|
| 96 |
+
const existingMessage = await db.select()
|
| 97 |
+
.from(messages)
|
| 98 |
+
.where(
|
| 99 |
+
and(
|
| 100 |
+
eq(messages.id, messageId),
|
| 101 |
+
eq(messages.senderId, userId)
|
| 102 |
+
)
|
| 103 |
+
)
|
| 104 |
+
.limit(1);
|
| 105 |
+
|
| 106 |
+
if (!existingMessage[0]) {
|
| 107 |
+
return false;
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
await db.delete(messages).where(eq(messages.id, messageId));
|
| 111 |
+
|
| 112 |
+
return true;
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
// =============================================================================
|
| 116 |
// Chat History
|
| 117 |
// =============================================================================
|