Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| # Social Features - LinkedIn/Facebook Style Following | |
| ## Overview | |
| The platform now includes comprehensive social networking features inspired by LinkedIn and Facebook, allowing users to follow and engage with: | |
| 1. **Leaders** - Elected officials, decision makers, community advocates | |
| 2. **Organizations** - Nonprofits, charities, government agencies | |
| 3. **Causes** - Policy topics and issues (oral health, housing, education, etc.) | |
| 4. **Other Users** - Fellow community members and advocates | |
| --- | |
| ## π― Features | |
| ### Follow System | |
| - β One-click follow/unfollow buttons (LinkedIn/Facebook style) | |
| - β Hover effects ("Following" β "Unfollow") | |
| - β Real-time follower counts | |
| - β Optimistic UI updates | |
| - β Persistent follow state across sessions | |
| ### Profile Page | |
| - β User profile with avatar, bio, location | |
| - β Follower/following statistics | |
| - β Tabbed interface showing: | |
| - Leaders you're following | |
| - Charities you're following | |
| - Causes you care about | |
| - β Breakdown by category (e.g., "Following 5 leaders, 3 charities, 2 causes") | |
| ### Social Stats Component | |
| - β Displays follower/following counts | |
| - β Shows breakdown of what user follows | |
| - β Clickable to view full lists | |
| - β LinkedIn-style presentation | |
| --- | |
| ## π Database Schema | |
| ### New Tables | |
| #### `leaders` | |
| Public officials and decision makers | |
| - `id` - Primary key | |
| - `name`, `slug` - Identity | |
| - `title`, `office` - Position details | |
| - `city`, `state`, `jurisdiction` - Location | |
| - `email`, `phone`, `website` - Contact | |
| - `twitter`, `linkedin`, `facebook` - Social media | |
| - `follower_count` - Denormalized count | |
| - `is_verified` - Verification badge | |
| #### `organizations` | |
| Nonprofits, charities, advocacy groups | |
| - `id` - Primary key | |
| - `name`, `slug` - Identity | |
| - `description`, `logo_url` - Branding | |
| - `org_type` - 'nonprofit', 'government', 'advocacy', 'charity' | |
| - `city`, `state`, `address` - Location | |
| - `ein`, `ntee_code`, `revenue` - IRS data | |
| - `follower_count` - Denormalized count | |
| - `is_verified` - Verification badge | |
| #### `causes` | |
| Policy topics and issues | |
| - `id` - Primary key | |
| - `name`, `slug` - Identity | |
| - `description`, `icon_url`, `color` - Visual identity | |
| - `category` - 'health', 'education', 'housing', 'environment', etc. | |
| - `follower_count` - Denormalized count | |
| #### Follow Relationship Tables | |
| All use composite unique constraints to prevent duplicate follows: | |
| - `user_follows` - User β User relationships | |
| - `leader_follows` - User β Leader relationships | |
| - `organization_follows` - User β Organization relationships | |
| - `cause_follows` - User β Cause relationships | |
| Each contains: | |
| - `user_id` - Foreign key to users | |
| - `{entity}_id` - Foreign key to entity | |
| - `created_at` - Timestamp | |
| --- | |
| ## π API Endpoints | |
| ### Follow Actions | |
| ```http | |
| POST /api/social/follow/user/{user_id} # Follow a user | |
| DELETE /api/social/follow/user/{user_id} # Unfollow a user | |
| POST /api/social/follow/leader/{leader_id} # Follow a leader | |
| DELETE /api/social/follow/leader/{leader_id} # Unfollow a leader | |
| POST /api/social/follow/organization/{org_id} # Follow an organization | |
| DELETE /api/social/follow/organization/{org_id} # Unfollow an organization | |
| POST /api/social/follow/cause/{cause_id} # Follow a cause | |
| DELETE /api/social/follow/cause/{cause_id} # Unfollow a cause | |
| ``` | |
| **Response:** | |
| ```json | |
| { | |
| "success": true, | |
| "following": true, | |
| "follower_count": 1234, | |
| "message": "Successfully followed leader" | |
| } | |
| ``` | |
| ### Check Following Status | |
| ```http | |
| GET /api/social/following/status?user_id=1&leader_id=2&org_id=3&cause_id=4 | |
| ``` | |
| **Response:** | |
| ```json | |
| { | |
| "user": false, | |
| "leader": true, | |
| "organization": true, | |
| "cause": false | |
| } | |
| ``` | |
| ### Get Statistics | |
| ```http | |
| GET /api/social/stats # Current user's stats | |
| GET /api/social/stats?user_id=123 # Another user's stats | |
| ``` | |
| **Response:** | |
| ```json | |
| { | |
| "followers": 150, | |
| "following": 42, | |
| "following_users": 10, | |
| "following_leaders": 15, | |
| "following_organizations": 12, | |
| "following_causes": 5 | |
| } | |
| ``` | |
| ### Get Following Lists | |
| ```http | |
| GET /api/social/following/leaders # Leaders you follow | |
| GET /api/social/following/organizations # Organizations you follow | |
| GET /api/social/following/causes # Causes you follow | |
| ``` | |
| **Response (Leaders):** | |
| ```json | |
| [ | |
| { | |
| "id": 1, | |
| "name": "Jane Smith", | |
| "slug": "jane-smith", | |
| "title": "Mayor", | |
| "office": "Office of the Mayor", | |
| "city": "Tuscaloosa", | |
| "state": "AL", | |
| "photo_url": "https://...", | |
| "follower_count": 1542, | |
| "is_verified": true | |
| } | |
| ] | |
| ``` | |
| --- | |
| ## π¨ UI Components | |
| ### FollowButton Component | |
| **Location:** `frontend/src/components/FollowButton.tsx` | |
| **Props:** | |
| ```typescript | |
| interface FollowButtonProps { | |
| type: 'user' | 'leader' | 'organization' | 'cause' | |
| id: number | |
| initialFollowing?: boolean | |
| initialCount?: number | |
| showCount?: boolean | |
| compact?: boolean | |
| onFollowChange?: (following: boolean, count: number) => void | |
| } | |
| ``` | |
| **Usage:** | |
| ```tsx | |
| // Compact button (for cards) | |
| <FollowButton | |
| type="leader" | |
| id={leader.id} | |
| initialFollowing={false} | |
| compact={true} | |
| /> | |
| // Full button with count | |
| <FollowButton | |
| type="organization" | |
| id={org.id} | |
| initialFollowing={true} | |
| initialCount={1234} | |
| showCount={true} | |
| /> | |
| ``` | |
| **Features:** | |
| - LinkedIn-style hover effect: "Following" β "Unfollow" (red) | |
| - Blue button when not following | |
| - White button with check mark when following | |
| - Loading spinner during API calls | |
| - Optimistic UI updates | |
| ### SocialStats Component | |
| **Location:** `frontend/src/components/SocialStats.tsx` | |
| **Props:** | |
| ```typescript | |
| interface SocialStatsProps { | |
| userId?: number // Optional, defaults to current user | |
| showBreakdown?: boolean // Show category breakdown | |
| clickable?: boolean // Link to profile page | |
| } | |
| ``` | |
| **Usage:** | |
| ```tsx | |
| // Show current user's stats | |
| <SocialStats showBreakdown={true} /> | |
| // Show another user's stats | |
| <SocialStats userId={123} showBreakdown={false} /> | |
| ``` | |
| **Features:** | |
| - Displays follower/following counts | |
| - Shows breakdown by category (leaders, charities, causes, people) | |
| - Colored category badges | |
| - Links to profile page (optional) | |
| --- | |
| ## π± Pages | |
| ### Profile Page | |
| **Route:** `/profile` | |
| **Location:** `frontend/src/pages/Profile.tsx` | |
| **Features:** | |
| - User avatar and basic info | |
| - Social statistics with breakdown | |
| - Tabbed interface: | |
| - **Leaders** - Grid of leader cards with follow buttons | |
| - **Charities** - Grid of organization cards with follow buttons | |
| - **Causes** - Grid of cause cards with follow buttons | |
| - Empty states with CTAs ("Find leaders to follow β") | |
| - Verification badges for verified entities | |
| ### Find Leaders Page (Updated) | |
| **Route:** `/people` | |
| **Location:** `frontend/src/pages/PeopleFinder.tsx` | |
| **Changes:** | |
| - Added follow button to each person card | |
| - Shows follower count | |
| - LinkedIn-style card layout with separator | |
| - Follow button at bottom of each card | |
| --- | |
| ## π Migration | |
| ### Run Database Migration | |
| ```bash | |
| cd /home/developer/projects/open-navigator | |
| source .venv/bin/activate | |
| python scripts/migrate_social_features.py | |
| ``` | |
| **Output:** | |
| ``` | |
| β Social features tables created successfully! | |
| π New tables: | |
| β leaders - Public officials and decision makers | |
| β organizations - Nonprofits and charities | |
| β causes - Policy topics and issues | |
| β user_follows - UserβUser follows | |
| β leader_follows - UserβLeader follows | |
| β organization_follows - UserβOrganization follows | |
| β cause_follows - UserβCause follows | |
| π Migration complete! Social features are ready to use. | |
| ``` | |
| --- | |
| ## π Next Steps | |
| ### 1. Seed Data | |
| Create seed data for leaders, organizations, and causes: | |
| ```python | |
| # scripts/seed_social_data.py | |
| from api.models import Leader, Organization, Cause | |
| from api.database import SessionLocal | |
| db = SessionLocal() | |
| # Add Tuscaloosa Mayor | |
| leader = Leader( | |
| name="Walter Maddox", | |
| slug="walter-maddox", | |
| title="Mayor", | |
| office="Office of the Mayor", | |
| city="Tuscaloosa", | |
| state="Alabama", | |
| jurisdiction="City of Tuscaloosa", | |
| email="mayor@tuscaloosa.com", | |
| follower_count=0, | |
| is_verified=True | |
| ) | |
| db.add(leader) | |
| # Add causes | |
| causes = [ | |
| Cause( | |
| name="Oral Health", | |
| slug="oral-health", | |
| description="Access to dental care and oral health education", | |
| category="health", | |
| color="#354F52", | |
| follower_count=0 | |
| ), | |
| Cause( | |
| name="Affordable Housing", | |
| slug="affordable-housing", | |
| description="Creating affordable housing opportunities", | |
| category="housing", | |
| color="#52796F", | |
| follower_count=0 | |
| ), | |
| # Add more... | |
| ] | |
| db.add_all(causes) | |
| db.commit() | |
| ``` | |
| ### 2. Activity Feed | |
| Create a feed showing updates from followed entities: | |
| - New meeting minutes from followed leaders | |
| - Updates from followed organizations | |
| - News about followed causes | |
| ### 3. Notifications | |
| Notify users when: | |
| - Someone follows them | |
| - A followed leader posts something | |
| - A followed organization has an update | |
| - Activity on a followed cause | |
| ### 4. Recommendations | |
| Suggest who to follow based on: | |
| - Location (follow local leaders) | |
| - Interests (follow related causes) | |
| - Network (follow people in your network) | |
| ### 5. Analytics | |
| Track engagement metrics: | |
| - Most followed leaders | |
| - Most popular causes | |
| - Follow growth over time | |
| - Engagement rates | |
| --- | |
| ## π¨ Design Principles | |
| ### LinkedIn/Facebook Patterns Used | |
| 1. **Follow Button States:** | |
| - Not following: Blue "Follow" button | |
| - Following: White "Following" button with check | |
| - Hover on following: Red "Unfollow" button | |
| 2. **Profile Layout:** | |
| - Large avatar at top | |
| - Stats prominently displayed | |
| - Tabbed content for different categories | |
| 3. **Social Proof:** | |
| - Follower counts visible everywhere | |
| - Verification badges for trusted entities | |
| - "X people follow this" messaging | |
| 4. **Discovery:** | |
| - Follow buttons on all entity cards | |
| - Empty states with clear CTAs | |
| - Category-based browsing | |
| ### Plain Language | |
| - β "Charities" instead of "Nonprofits" | |
| - β "Leaders" instead of "Officials" | |
| - β "Following" instead of "Subscribed" | |
| - β "Followers" instead of "Subscribers" | |
| --- | |
| ## π Authentication | |
| All follow endpoints require authentication: | |
| - User must be logged in via OAuth (HuggingFace, Google, Facebook, GitHub) | |
| - JWT token passed in Authorization header | |
| - `get_current_user` dependency validates token | |
| **Error Responses:** | |
| ```json | |
| { | |
| "detail": "Not authenticated" | |
| } | |
| ``` | |
| --- | |
| ## π Resources | |
| ### API Documentation | |
| - Swagger UI: http://localhost:8000/docs | |
| - ReDoc: http://localhost:8000/redoc | |
| ### Code Files | |
| - **Backend:** | |
| - `api/models.py` - Database models | |
| - `api/routes/social.py` - API endpoints | |
| - `scripts/migrate_social_features.py` - Migration script | |
| - **Frontend:** | |
| - `frontend/src/components/FollowButton.tsx` - Follow button component | |
| - `frontend/src/components/SocialStats.tsx` - Stats display component | |
| - `frontend/src/pages/Profile.tsx` - Profile page | |
| - `frontend/src/pages/PeopleFinder.tsx` - Updated with follow buttons | |
| --- | |
| ## π Summary | |
| You now have a complete social networking system for civic engagement! Users can: | |
| 1. **Follow leaders** they care about | |
| 2. **Follow charities** doing important work | |
| 3. **Follow causes** they're passionate about | |
| 4. **Follow other users** in their network | |
| 5. **View their profile** with social stats | |
| 6. **See who they follow** in organized tabs | |
| This transforms the platform from a read-only information source into an **engaging social network for civic participation**! π | |