# Social Connections System — Implementation Plan See the full plan in the conversation transcript. This file tracks implementation progress. ## Phase Status | Phase | Description | Status | |-------|-------------|--------| | 1 | Feature Flag + Social Module Skeleton | COMPLETE | | 2 | Friendship API (Send, Accept, Decline, Cancel, Unfriend) | COMPLETE | | 3 | Block/Unblock API + Privacy Settings API | COMPLETE | | 4 | User Social Profile + Volunteer Portal UI Foundation | COMPLETE | | 5 | In-App Notification System (Bell Icon + Dropdown) | COMPLETE | | 6 | Social Activity Feed (Friends' Activities) | COMPLETE | | 7 | CRM Bridge (Auto-Connect + Friend Suggestions) | COMPLETE | | 8 | Poke System + Video Recommendations | COMPLETE | | 9 | Close Friends + Friends Management Page | COMPLETE (merged into Phase 4 UI) | | 10 | Email Digest Notifications | COMPLETE | | 11 | Social Integration with Existing Features | COMPLETE | | 12 | Rocket.Chat DM Integration | COMPLETE | | 13 | Group/Team Features (Shift Teams, Campaign Teams) | COMPLETE | | 14 | Gamification (Achievements, Streaks, Leaderboards) | COMPLETE | | 15 | Real-Time Features (SSE for Live Notifications, Online Status) | COMPLETE | ## Files Created/Modified ### Backend (API) - `api/prisma/schema.prisma` — added `enableSocial` to SiteSettings - `api/prisma/migrations/20260224215259_add_enable_social/` — migration - `api/src/modules/social/` — new module directory - `social.routes.ts` — main router mounting sub-routers - `social.schemas.ts` — Zod schemas (friendship, privacy, notification) - `social.middleware.ts` — `checkSocialEnabled` feature gate - `social.rate-limits.ts` — rate limiters (friend request, social action) - `friendship.service.ts` — full friendship CRUD + notifications - `friendship.routes.ts` — 10 friendship endpoints - `block.service.ts` — block/unblock with auto-unfriend - `block.routes.ts` — 3 block endpoints - `privacy.service.ts` — privacy settings get/update (auto-create defaults) - `privacy.routes.ts` — 2 privacy endpoints - `notification.service.ts` — notification CRUD + preferences (respects opt-outs) - `notification.routes.ts` — 7 notification endpoints - `profile.routes.ts` — user profile view (own + other, privacy-filtered) - `api/src/modules/settings/settings.schemas.ts` — added `enableSocial` - `api/src/server.ts` — mounted socialRouter at `/api/social` ### Frontend (Admin) - `admin/src/types/social.ts` — TypeScript interfaces - `admin/src/stores/social.store.ts` — Zustand social store - `admin/src/components/social/` — new directory - `UserAvatar.tsx` — initials avatar with userId-based color - `FriendButton.tsx` — context-aware friend action button - `NotificationBell.tsx` — bell icon + dropdown (30s polling) - `admin/src/pages/volunteer/` — new pages - `SocialProfilePage.tsx` — own + other user profile - `FriendsPage.tsx` — friends management (tabs: friends, requests, sent, blocked) - `NotificationsPage.tsx` — full notification list + preferences - `admin/src/components/VolunteerLayout.tsx` — added NotificationBell - `admin/src/components/VolunteerFooterNav.tsx` — added "Friends" nav item - `admin/src/components/FeatureGate.tsx` — added `enableSocial` - `admin/src/types/api.ts` — added `enableSocial` to SiteSettings - `admin/src/pages/SettingsPage.tsx` — added toggle - `admin/src/App.tsx` — added 6 new volunteer routes ### Phase 6 — Social Activity Feed - `api/src/modules/social/feed.service.ts` — aggregates 4 activity types + Redis cache (2-min TTL) - `api/src/modules/social/feed.routes.ts` — GET `/` (friend feed), GET `/my` (own activity) - `admin/src/components/social/FeedCard.tsx` — activity card with type-based icon/color - `admin/src/pages/volunteer/SocialFeedPage.tsx` — feed page with suggestions widget ### Phase 7 — CRM Bridge + Suggestions - `api/src/modules/social/suggestions.service.ts` — ranked suggestions (household/mutual/shifts/campaigns) - `api/src/modules/social/suggestions.routes.ts` — GET `/`, POST `/:userId/dismiss` - `admin/src/components/social/FriendSuggestions.tsx` — horizontal scroll suggestions widget - `admin/src/pages/volunteer/DiscoverPage.tsx` — search + suggestions page ### Phase 8 — Poke System + Video Recommendations - `api/src/modules/social/poke.service.ts` — poke CRUD + 24h Redis cooldown per pair - `api/src/modules/social/poke.routes.ts` — POST `/`, GET `/`, GET `/count`, POST `/:id/read`, GET `/cooldown/:userId` - `api/src/modules/social/recommendation.service.ts` — video recommendation CRUD + duplicate detection - `api/src/modules/social/recommendation.routes.ts` — POST `/`, GET `/`, GET `/sent`, GET `/count`, POST `/:id/read` - `admin/src/components/social/PokeButton.tsx` — poke button with cooldown indicator - `admin/src/components/social/RecommendVideoModal.tsx` — friend + video picker modal - `admin/src/pages/volunteer/SocialProfilePage.tsx` — added PokeButton ### Phase 10 — Email Digest Notifications - `api/prisma/migrations/20260224232546_add_digest_frequency/` — adds digestFrequency + lastDigestSentAt - `api/src/services/social-digest.service.ts` — daily scan, generates digest emails - `api/src/templates/email/social-digest.html` + `.txt` — digest email templates - `api/src/server.ts` — added daily social digest scan interval - `admin/src/pages/volunteer/NotificationsPage.tsx` — added digest frequency selector ### Phase 11 — Social Integration with Existing Features - `api/src/modules/social/integration.service.ts` — friends on shifts, campaigns, and active map sessions (privacy-filtered) - `api/src/modules/social/integration.routes.ts` — 3 endpoints: shifts/:id/friends, campaigns/:id/friends, map/friends - `admin/src/components/social/FriendsAttendingBadge.tsx` — "N friends attending" badge with stacked avatars - `admin/src/components/social/FriendsCampaignBadge.tsx` — "N friends participated" badge with stacked avatars - `admin/src/components/social/FriendsOnMap.tsx` — floating panel showing friends currently canvassing (60s poll) - `admin/src/pages/public/ShiftsPage.tsx` — added FriendsAttendingBadge per shift card - `admin/src/pages/public/CampaignPage.tsx` — added FriendsCampaignBadge in hero section - `admin/src/pages/volunteer/VolunteerShiftsPage.tsx` — added FriendsAttendingBadge per shift card - `admin/src/pages/volunteer/VolunteerMapPage.tsx` — added FriendsOnMap overlay - `admin/src/types/social.ts` — added FriendOnShift, FriendOnCampaign, FriendOnMap types ### Phase 12 — Rocket.Chat DM Integration - `api/src/modules/social/messaging.service.ts` — openDM: provisions both users, creates DM room, returns roomId - `api/src/modules/social/profile.routes.ts` — added POST `/:userId/dm` endpoint - `api/src/services/rocketchat.client.ts` — added `createDM(usernames)` method - `admin/src/components/social/MessageButton.tsx` — DM button (opens chat widget, RC-gated) - `admin/src/pages/volunteer/SocialProfilePage.tsx` — added MessageButton for accepted friends ### Phase 13 — Group/Team Features - `api/prisma/schema.prisma` — added SocialGroup, SocialGroupMember models + SocialGroupType enum + User.socialGroupMemberships relation - `api/prisma/migrations/20260225000017_add_social_groups/` — migration creating social_groups + social_group_members tables - `api/src/modules/social/group.service.ts` — getOrCreate, syncShiftTeam, syncCampaignTeam, listMyGroups, getGroupDetail - `api/src/modules/social/group.routes.ts` — GET `/` (my groups), GET `/:id` (group detail) - `api/src/modules/social/social.routes.ts` — mounted groupRouter at `/groups` - `api/src/modules/map/shifts/shifts.service.ts` — added fire-and-forget groupService.syncShiftTeam() on all signup/cancel events - `api/src/modules/influence/campaign-emails/campaign-emails.service.ts` — added fire-and-forget groupService.syncCampaignTeam() on email creation - `admin/src/types/social.ts` — added SocialGroupSummary, SocialGroupDetail interfaces - `admin/src/components/social/GroupCard.tsx` — group card with type-based icon/color - `admin/src/pages/volunteer/GroupDetailPage.tsx` — group detail with member list + FriendButton per member - `admin/src/pages/volunteer/FriendsPage.tsx` — added "Groups" tab - `admin/src/App.tsx` — added `/volunteer/groups/:id` route ### Phase 14 — Gamification (Achievements, Streaks, Leaderboards) - `api/src/modules/social/achievements.service.ts` — 11 achievements (4 shift, 4 canvass, 2 campaign, 2 social), checkAndUnlock, getLeaderboard (raw SQL), getVolunteerStats (on-the-fly computed) - `api/src/modules/social/achievements.routes.ts` — 6 endpoints: achievements, definitions, stats, stats/:userId, user/:userId, leaderboard - `api/src/modules/social/social.routes.ts` — mounted achievementsRouter at `/achievements` - `api/src/modules/map/canvass/canvass.service.ts` — added achievements.checkAndUnlock after recordVisit - `api/src/modules/map/shifts/shifts.service.ts` — added achievements.checkAndUnlock after signup events (admin, public, volunteer) - `api/src/modules/influence/campaign-emails/campaign-emails.service.ts` — added achievements.checkAndUnlock after email creation - `api/src/modules/social/friendship.service.ts` — added achievements.checkAndUnlock on friend accept (both users) - `admin/src/types/social.ts` — added AchievementDef, AchievementWithProgress, VolunteerStats, LeaderboardEntry interfaces - `admin/src/pages/volunteer/AchievementsPage.tsx` — badge gallery (locked/unlocked + progress bars), volunteer stats summary, leaderboard (canvass/shifts/campaigns tabs) - `admin/src/pages/volunteer/SocialProfilePage.tsx` — added achievement badges section to own + other user profiles - `admin/src/pages/volunteer/SocialFeedPage.tsx` — added top canvassers leaderboard widget - `admin/src/App.tsx` — added `/volunteer/achievements` route ### Phase 15 — Real-Time Features (SSE for Live Notifications, Online Status) - `api/src/modules/social/sse.service.ts` — in-memory SSE connection manager (addClient, removeClient, sendToUser, sendToUsers, heartbeat, closeAll) - `api/src/modules/social/presence.service.ts` — online/offline tracking with privacy filtering, broadcastPresence to friends, stale cleanup (5min timeout), markAllOffline (startup) - `api/src/modules/social/sse.routes.ts` — GET `/` (SSE stream), GET `/online-friends`, GET `/status` - `api/src/modules/social/social.routes.ts` — mounted sseRouter at `/sse`, added query-param token injection for EventSource auth - `api/src/modules/social/notification.service.ts` — SSE push after notification creation (real-time delivery) - `api/src/modules/social/friendship.service.ts` — SSE push on friend_request + friend_accepted events - `api/src/modules/social/poke.service.ts` — SSE push on poke events - `api/src/server.ts` — SSE heartbeat start, presenceService.markAllOffline on startup, 1-min stale cleanup interval, sseService.closeAll on graceful shutdown - `admin/src/hooks/useSSE.ts` — EventSource hook with auto-reconnect (exponential backoff), handles notification/presence/friend_request/friend_accepted/poke events - `admin/src/components/social/OnlineIndicator.tsx` — green dot showing online status for friends - `admin/src/components/social/UserAvatar.tsx` — added showOnline prop with OnlineIndicator overlay - `admin/src/stores/social.store.ts` — added onlineFriends state + fetchOnlineFriends action - `admin/src/components/VolunteerLayout.tsx` — initialized useSSE() on mount - `admin/src/components/social/NotificationBell.tsx` — reduced polling to 2-min fallback (SSE handles real-time) - `admin/src/pages/volunteer/FriendsPage.tsx` — enabled showOnline on friend list avatars - `admin/src/pages/volunteer/SocialProfilePage.tsx` — enabled showOnline on other user profile avatars