Skip to content

Commit 36c2d86

Browse files
committed
fixed support and me too buttons. fixed some problems with analysis page lads when ai is not available.
1 parent 1d99ba8 commit 36c2d86

23 files changed

+715
-195
lines changed

.github/workflows/azure-deploy.yml

Lines changed: 0 additions & 68 deletions
This file was deleted.

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,4 +294,7 @@ tramp
294294
# Add any project-specific files or directories here
295295
uploads/
296296
temp-files/
297-
*.tmp
297+
*.tmp
298+
299+
# WARP.md - AI assistant context file
300+
WARP.md

backend/src/controllers/userController.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { Request, Response } from 'express';
22
import { body, query, validationResult } from 'express-validator';
33
import { UserService } from '../services/userService';
4+
import { LikeService } from '../services/likeService';
45
import { UpdateProfileRequest, UserSearchQuery } from '../types/user';
56

67
const userService = new UserService();
8+
const likeService = new LikeService();
79

810
// Validation rules
911
export const updateProfileValidation = [
@@ -279,4 +281,39 @@ export class UserController {
279281
});
280282
}
281283
}
282-
}
284+
285+
async getUserLikes(req: Request, res: Response) {
286+
try {
287+
const { userId } = req.params;
288+
const limit = req.query.limit ? parseInt(req.query.limit as string) : 20;
289+
const offset = req.query.offset ? parseInt(req.query.offset as string) : 0;
290+
291+
if (!userId) {
292+
return res.status(400).json({
293+
error: {
294+
code: 'MISSING_USER_ID',
295+
message: 'User ID is required',
296+
},
297+
timestamp: new Date().toISOString(),
298+
path: req.path,
299+
});
300+
}
301+
302+
// For now, return empty array since this is a complex query
303+
// TODO: Implement in LikeService to get posts liked by user
304+
res.json({
305+
data: [],
306+
message: 'User likes endpoint - to be implemented'
307+
});
308+
} catch (error: any) {
309+
res.status(500).json({
310+
error: {
311+
code: 'USER_LIKES_FETCH_FAILED',
312+
message: 'Failed to fetch user likes',
313+
},
314+
timestamp: new Date().toISOString(),
315+
path: req.path,
316+
});
317+
}
318+
}
319+
}

backend/src/controllers/worryResolutionController.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ export class WorryResolutionController {
222222
return res.status(404).json({
223223
error: {
224224
code: 'RESOLUTION_NOT_FOUND',
225-
message: 'Resolution not found or not accessible',
225+
message: 'No resolution found for this post',
226226
},
227227
timestamp: new Date().toISOString(),
228228
path: req.path,

backend/src/index.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ import worryAnalysisRoutes from "./routes/worryAnalysis";
185185
import subscriptionRoutes from "./routes/subscriptions";
186186
import analyticsRoutes from "./routes/analytics";
187187
import demographicAnalyticsRoutes from "./routes/demographicAnalytics";
188-
import worryResolutionRoutes from "./routes/worryResolution";
188+
import { worryResolutionRoutes } from "./routes/worryResolution";
189189
import notificationsRoutes from "./routes/notifications";
190190
import languagesRoutes from "./routes/languages";
191191
import dashboardRoutes from "./routes/dashboard";
@@ -211,13 +211,7 @@ app.use("/api/analytics", analyticsRoutes);
211211
app.use("/api/demographics", demographicAnalyticsRoutes);
212212
app.use("/api/resolutions", worryResolutionRoutes);
213213

214-
console.log('🎯 --- REGISTERED RESOLUTION ROUTES ---');
215-
worryResolutionRoutes.stack.forEach(function(r){
216-
if (r.route && r.route.path){
217-
console.log(r.route.path)
218-
}
219-
});
220-
console.log('------------------------------------');
214+
221215
app.use("/api/wellness", wellnessRoutes);
222216
app.use("/api/notifications", notificationsRoutes);
223217
app.use("/api/languages", languagesRoutes);
@@ -325,6 +319,14 @@ const server = app.listen(PORT, async () => {
325319
// Simple ready message
326320
console.log(`🎯 Worrybox API server ready and running on port ${PORT}`);
327321

322+
console.log('🎯 --- REGISTERED RESOLUTION ROUTES ---');
323+
worryResolutionRoutes.stack.forEach(function(r){
324+
if (r.route && r.route.path){
325+
console.log(r.route.path)
326+
}
327+
});
328+
console.log('------------------------------------');
329+
328330
if (isDevelopment) {
329331
logger.info("🎯 Worrybox API server ready and running", {
330332
port: PORT,

backend/src/routes/users.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ router.get('/profile', authenticateToken, userController.getProfile);
1212
// Public routes (no authentication required)
1313
router.get('/search', searchUsersValidation, userController.searchUsers);
1414
router.get('/username/:username', userController.getUserByUsername);
15+
router.get('/:userId/likes', userController.getUserLikes);
1516

1617
// Semi-protected routes (optional authentication)
1718
router.get('/username-available/:username', optionalAuth, userController.checkUsernameAvailability);

backend/src/routes/worryResolution.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const worryResolutionController = new WorryResolutionController();
1717

1818
// Public routes (no authentication required)
1919
router.get('/stories', getPublicResolutionStoriesValidation, worryResolutionController.getPublicResolutionStories);
20+
// Allow public access to check if a resolution exists for a post
21+
router.get('/posts/:postId', worryResolutionController.getResolution);
2022

2123
// Protected routes (authentication required)
2224
router.use(authenticateToken);
@@ -25,13 +27,10 @@ router.use(authenticateToken);
2527
router.post('/posts/:postId/resolve', resolveWorryValidation, worryResolutionController.resolveWorry);
2628
router.put('/posts/:postId/resolve', updateResolutionValidation, worryResolutionController.updateResolution);
2729
router.delete('/posts/:postId/resolve', getResolutionValidation, worryResolutionController.unresolveWorry);
28-
29-
// Get resolution data
30-
router.get('/posts/:postId', worryResolutionController.getResolution);
3130
router.get('/users/:userId/resolved', getUserResolvedWorriesValidation, worryResolutionController.getUserResolvedWorries);
3231
router.get('/stats', worryResolutionController.getResolutionStats);
3332

3433
// Resolution suggestions
3534
router.get('/posts/:postId/suggestions', getResolutionSuggestionsValidation, worryResolutionController.getResolutionSuggestions);
3635

37-
export default router;
36+
export { router as worryResolutionRoutes };

backend/src/services/postService.ts

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -640,32 +640,30 @@ export class PostService {
640640
userHasMeToo?: boolean;
641641
}> {
642642
try {
643-
// Get all interaction counts in parallel with proper error handling
643+
// Isolate the AI analysis query to prevent it from crashing the entire data fetch
644+
let worryAnalysis: { similarWorryCount: number } | null = null;
645+
try {
646+
worryAnalysis = await prisma.worryAnalysis.findUnique({
647+
where: { postId },
648+
select: { similarWorryCount: true },
649+
});
650+
} catch (e) {
651+
console.error(`AI analysis query failed for post ${postId}. Returning post without it.`, e);
652+
// On failure, worryAnalysis remains null, which is handled below
653+
}
654+
655+
// Get other interaction counts in parallel
644656
const [
645657
supportCount,
646658
meTooCount,
647-
worryAnalysis,
648659
userSupport,
649660
userMeToo
650661
] = await Promise.all([
651-
// Support count - handle potential errors gracefully
652662
prisma.like.count({ where: { postId } }).catch(() => 0),
653-
654-
// MeToo count - handle potential errors gracefully
655663
prisma.meToo.count({ where: { postId } }).catch(() => 0),
656-
657-
// AI similar worry count from analysis - handle missing analysis
658-
prisma.worryAnalysis.findUnique({
659-
where: { postId },
660-
select: { similarWorryCount: true }
661-
}).catch(() => null),
662-
663-
// User's support status (if requesting user provided)
664664
requestingUserId ? prisma.like.findFirst({
665665
where: { postId, userId: requestingUserId }
666666
}).catch(() => null) : Promise.resolve(null),
667-
668-
// User's MeToo status (if requesting user provided)
669667
requestingUserId ? prisma.meToo.findFirst({
670668
where: { postId, userId: requestingUserId }
671669
}).catch(() => null) : Promise.resolve(null)
@@ -684,8 +682,8 @@ export class PostService {
684682
userHasMeToo: requestingUserId ? !!userMeToo : undefined,
685683
};
686684
} catch (error) {
687-
// If there's a critical error, return safe defaults
688-
console.error('Error fetching post interaction data:', error);
685+
// If there's a critical error in the main block, return safe defaults
686+
console.error('Critical error fetching post interaction data:', error);
689687
return {
690688
supportCount: 0,
691689
meTooCount: 0,

frontend/src/components/CommentSection.tsx

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { commentService, CommentResponse } from '../services/commentService'
44
import { MessageCircle, Send, Edit2, Trash2, Loader2, Reply, Flag, AlertTriangle } from 'lucide-react'
55
import UserAvatar from './UserAvatar'
66
import toast from 'react-hot-toast'
7+
import { apiRequest } from '../utils/requestQueue'
78

89
interface CommentSectionProps {
910
postId: string
@@ -34,9 +35,10 @@ const CommentSection: React.FC<CommentSectionProps> = ({ postId, className = '',
3435
const loadComments = async () => {
3536
try {
3637
setIsLoading(true)
38+
// Use request queue with normal priority for comments
3739
const [commentsData, count] = await Promise.all([
38-
commentService.getCommentsWithReplies(postId, 10, 0), // Use threaded comments
39-
commentService.getCommentCount(postId)
40+
apiRequest.normal(() => commentService.getCommentsWithReplies(postId, 10, 0), `comments-${postId}`),
41+
apiRequest.normal(() => commentService.getCommentCount(postId), `comment-count-${postId}`)
4042
])
4143
setComments(commentsData.comments)
4244
setCommentCount(count)
@@ -62,9 +64,10 @@ const CommentSection: React.FC<CommentSectionProps> = ({ postId, className = '',
6264

6365
setIsSubmitting(true)
6466
try {
65-
const comment = await commentService.createComment(postId, {
67+
// Use high priority for user interactions
68+
const comment = await apiRequest.high(() => commentService.createComment(postId, {
6669
content: newComment.trim()
67-
})
70+
}))
6871
setComments(prev => [comment, ...prev])
6972
setCommentCount(prev => prev + 1)
7073
setNewComment('')
@@ -80,9 +83,10 @@ const CommentSection: React.FC<CommentSectionProps> = ({ postId, className = '',
8083
if (!editContent.trim()) return
8184

8285
try {
83-
const updatedComment = await commentService.updateComment(commentId, {
86+
// Use high priority for user interactions
87+
const updatedComment = await apiRequest.high(() => commentService.updateComment(commentId, {
8488
content: editContent.trim()
85-
})
89+
}))
8690
setComments(prev => prev.map(c => c.id === commentId ? updatedComment : c))
8791
setEditingComment(null)
8892
setEditContent('')
@@ -96,7 +100,8 @@ const CommentSection: React.FC<CommentSectionProps> = ({ postId, className = '',
96100
if (!confirm('Are you sure you want to delete this comment?')) return
97101

98102
try {
99-
await commentService.deleteComment(commentId)
103+
// Use high priority for user interactions
104+
await apiRequest.high(() => commentService.deleteComment(commentId))
100105
setComments(prev => prev.filter(c => c.id !== commentId))
101106
setCommentCount(prev => prev - 1)
102107
toast.success('Comment deleted successfully')
@@ -113,10 +118,11 @@ const CommentSection: React.FC<CommentSectionProps> = ({ postId, className = '',
113118
if (!replyContent.trim()) return
114119

115120
try {
116-
const reply = await commentService.createComment(postId, {
121+
// Use high priority for user interactions
122+
const reply = await apiRequest.high(() => commentService.createComment(postId, {
117123
content: replyContent.trim(),
118124
parentCommentId
119-
})
125+
}))
120126

121127
// Add reply to the parent comment's replies array
122128
setComments(prev => prev.map(comment => {
@@ -145,10 +151,11 @@ const CommentSection: React.FC<CommentSectionProps> = ({ postId, className = '',
145151
}
146152

147153
try {
148-
await commentService.reportComment(commentId, {
154+
// Use normal priority for reporting
155+
await apiRequest.normal(() => commentService.reportComment(commentId, {
149156
reason: reportReason,
150157
details: reportDetails || undefined
151-
})
158+
}))
152159

153160
setReportingComment(null)
154161
setReportReason('spam')

0 commit comments

Comments
 (0)