+ Manage your profile and preferences +
+@{currentUser.username}
+{currentUser.email}
++ Enter a direct link to an image +
+Profile updated successfully!
+ )} + {updateError && ( +{updateError}
+ )} +{challenge.name}
++ {new Date(challenge.startDate).toLocaleDateString()} -{" "} + {new Date(challenge.endDate).toLocaleDateString()} +
++ You're not participating in any challenges yet. +
+ )} + +@{user.username}
- {/* Follow Button */} - {followData && !followData.isOwnProfile && ( - + {/* Settings Button (own profile) or Follow Button */} + {followData && ( + followData.isOwnProfile ? ( + + ) : ( + + ) )} diff --git a/packages/backend/queries/participations.ts b/packages/backend/queries/participations.ts index 01c59208..b872cd98 100644 --- a/packages/backend/queries/participations.ts +++ b/packages/backend/queries/participations.ts @@ -5,6 +5,7 @@ import { getCurrentUser } from "../lib/ids"; import { getChallengeWeekNumber, getWeekDateRange, getTotalWeeks } from "../lib/weeks"; import type { Id } from "../_generated/dataModel"; import { notDeleted } from "../lib/activityFilters"; +import { dateOnlyToUtcMs } from "../lib/dateOnly"; /** * Get recent participants for a challenge @@ -247,6 +248,36 @@ export const getMentionable = query({ } }); +/** + * Get all challenges a user is participating in + */ +export const getUserChallenges = query({ + args: { + userId: v.id("users"), + }, + handler: async (ctx, args) => { + const participations = await ctx.db + .query("userChallenges") + .withIndex("userId", (q) => q.eq("userId", args.userId)) + .collect(); + + const challenges = await Promise.all( + participations.map(async (p) => { + const challenge = await ctx.db.get(p.challengeId); + return challenge; + }) + ); + + return challenges + .filter((c): c is NonNullable