changemaker.lite/SOCIAL_SYSTEM_PLAN.md

157 lines
12 KiB
Markdown

# 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