Prettier format pending files

This commit is contained in:
Builder.io 2025-11-11 00:50:12 +00:00
parent 77750af0da
commit 08c038b954
6 changed files with 250 additions and 76 deletions

View file

@ -20,7 +20,10 @@ export async function createNotification(
} }
} }
export async function notifyAccountLinked(userId: string, provider: string): Promise<void> { export async function notifyAccountLinked(
userId: string,
provider: string,
): Promise<void> {
await createNotification( await createNotification(
userId, userId,
"success", "success",

View file

@ -141,11 +141,18 @@ const ensureDailyStreakForProfile = async (
}; };
}; };
export function checkProfileComplete(p?: AethexUserProfile | null, roles?: string[]): boolean { export function checkProfileComplete(
p?: AethexUserProfile | null,
roles?: string[],
): boolean {
if (!p) return false; if (!p) return false;
// Admins/owners are always considered complete // Admins/owners are always considered complete
if (roles?.some((r) => ["owner", "admin", "founder", "staff"].includes(r.toLowerCase()))) { if (
roles?.some((r) =>
["owner", "admin", "founder", "staff"].includes(r.toLowerCase()),
)
) {
return true; return true;
} }
@ -542,7 +549,10 @@ export const aethexUserService = {
"You've completed your profile setup. Let's get started!", "You've completed your profile setup. Let's get started!",
); );
} catch (notifError) { } catch (notifError) {
console.warn("Failed to create onboarding notification:", notifError); console.warn(
"Failed to create onboarding notification:",
notifError,
);
} }
} }
@ -757,7 +767,10 @@ export const aethexProjectService = {
); );
} }
} catch (notifError) { } catch (notifError) {
console.warn("Failed to create project status notification:", notifError); console.warn(
"Failed to create project status notification:",
notifError,
);
} }
} }

View file

@ -31,7 +31,11 @@ export const notificationTriggers = {
} }
}, },
async addedToTeam(userId: string, teamName: string, role: string): Promise<void> { async addedToTeam(
userId: string,
teamName: string,
role: string,
): Promise<void> {
try { try {
await aethexNotificationService.createNotification( await aethexNotificationService.createNotification(
userId, userId,
@ -57,7 +61,11 @@ export const notificationTriggers = {
} }
}, },
async addedToProject(userId: string, projectName: string, role: string): Promise<void> { async addedToProject(
userId: string,
projectName: string,
role: string,
): Promise<void> {
try { try {
await aethexNotificationService.createNotification( await aethexNotificationService.createNotification(
userId, userId,
@ -155,13 +163,22 @@ export const notificationTriggers = {
message: string, message: string,
): Promise<void> { ): Promise<void> {
try { try {
await aethexNotificationService.createNotification(userId, type, title, message); await aethexNotificationService.createNotification(
userId,
type,
title,
message,
);
} catch (error) { } catch (error) {
console.warn("Failed to create custom notification:", error); console.warn("Failed to create custom notification:", error);
} }
}, },
async taskAssigned(userId: string, taskTitle: string, assignerName: string): Promise<void> { async taskAssigned(
userId: string,
taskTitle: string,
assignerName: string,
): Promise<void> {
try { try {
await aethexNotificationService.createNotification( await aethexNotificationService.createNotification(
userId, userId,
@ -187,7 +204,11 @@ export const notificationTriggers = {
} }
}, },
async postCommented(userId: string, commenterName: string, preview: string): Promise<void> { async postCommented(
userId: string,
commenterName: string,
preview: string,
): Promise<void> {
try { try {
await aethexNotificationService.createNotification( await aethexNotificationService.createNotification(
userId, userId,
@ -200,7 +221,11 @@ export const notificationTriggers = {
} }
}, },
async applicationReceived(userId: string, creatorName: string, opportunityTitle: string): Promise<void> { async applicationReceived(
userId: string,
creatorName: string,
opportunityTitle: string,
): Promise<void> {
try { try {
await aethexNotificationService.createNotification( await aethexNotificationService.createNotification(
userId, userId,
@ -218,13 +243,23 @@ export const notificationTriggers = {
status: "accepted" | "rejected" | "reviewed", status: "accepted" | "rejected" | "reviewed",
message?: string, message?: string,
): Promise<void> { ): Promise<void> {
const statusEmoji = status === "accepted" ? "✅" : status === "rejected" ? "❌" : "📝"; const statusEmoji =
const statusMessage = status === "accepted" ? "accepted" : status === "rejected" ? "rejected" : "reviewed"; status === "accepted" ? "✅" : status === "rejected" ? "❌" : "📝";
const statusMessage =
status === "accepted"
? "accepted"
: status === "rejected"
? "rejected"
: "reviewed";
try { try {
await aethexNotificationService.createNotification( await aethexNotificationService.createNotification(
userId, userId,
status === "accepted" ? "success" : status === "rejected" ? "error" : "info", status === "accepted"
? "success"
: status === "rejected"
? "error"
: "info",
`${statusEmoji} Application ${statusMessage}`, `${statusEmoji} Application ${statusMessage}`,
message || `Your application has been ${statusMessage}.`, message || `Your application has been ${statusMessage}.`,
); );
@ -233,7 +268,11 @@ export const notificationTriggers = {
} }
}, },
async newDeviceLogin(userId: string, deviceName: string, location?: string): Promise<void> { async newDeviceLogin(
userId: string,
deviceName: string,
location?: string,
): Promise<void> {
try { try {
await aethexNotificationService.createNotification( await aethexNotificationService.createNotification(
userId, userId,
@ -246,7 +285,10 @@ export const notificationTriggers = {
} }
}, },
async moderationReportSubmitted(userId: string, reportType: string): Promise<void> { async moderationReportSubmitted(
userId: string,
reportType: string,
): Promise<void> {
try { try {
await aethexNotificationService.createNotification( await aethexNotificationService.createNotification(
userId, userId,

View file

@ -7,72 +7,84 @@ A comprehensive notification system covering 15+ user interactions across social
## All Notification Flows ## All Notification Flows
### 1. Achievements (✅ Success) ### 1. Achievements (✅ Success)
**When:** User earns an achievement **When:** User earns an achievement
**Who Notified:** Achievement earner **Who Notified:** Achievement earner
**Format:** `🏆 Achievement Unlocked: {name}` - "{xp} XP awarded" **Format:** `🏆 Achievement Unlocked: {name}` - "{xp} XP awarded"
**Service:** `aethexAchievementService.awardAchievement()` **Service:** `aethexAchievementService.awardAchievement()`
### 2. Team Creation (✅ Success) ### 2. Team Creation (✅ Success)
**When:** Team is created **When:** Team is created
**Who Notified:** Team creator **Who Notified:** Team creator
**Format:** `🎯 Team Created: {name}` - "Your team is ready to go!" **Format:** `🎯 Team Created: {name}` - "Your team is ready to go!"
**Service:** `aethexCollabService.createTeam()` **Service:** `aethexCollabService.createTeam()`
### 3. Added to Team ( Info) ### 3. Added to Team ( Info)
**When:** User is added to a team **When:** User is added to a team
**Who Notified:** New team member **Who Notified:** New team member
**Format:** `👥 Added to Team: {name}` - "You've been added as a {role}" **Format:** `👥 Added to Team: {name}` - "You've been added as a {role}"
**Service:** `aethexCollabService.addTeamMember()` **Service:** `aethexCollabService.addTeamMember()`
### 4. Project Creation (✅ Success) ### 4. Project Creation (✅ Success)
**When:** Project is created **When:** Project is created
**Who Notified:** Project creator **Who Notified:** Project creator
**Format:** `🚀 Project Created: {name}` - "Your project is ready to go!" **Format:** `🚀 Project Created: {name}` - "Your project is ready to go!"
**Service:** `aethexProjectService.createProject()` **Service:** `aethexProjectService.createProject()`
### 5. Added to Project ( Info) ### 5. Added to Project ( Info)
**When:** User is added to a project **When:** User is added to a project
**Who Notified:** New project member **Who Notified:** New project member
**Format:** `📌 Added to Project: {name}` - "You've been added as a {role}" **Format:** `📌 Added to Project: {name}` - "You've been added as a {role}"
**Service:** `aethexCollabService.addProjectMember()` **Service:** `aethexCollabService.addProjectMember()`
### 6. Project Completed (✅ Success) ### 6. Project Completed (✅ Success)
**When:** Project status changes to completed **When:** Project status changes to completed
**Who Notified:** Project owner **Who Notified:** Project owner
**Format:** `✅ Project Completed: {name}` - "Congratulations!" **Format:** `✅ Project Completed: {name}` - "Congratulations!"
**Service:** `aethexProjectService.updateProject(status: "completed")` **Service:** `aethexProjectService.updateProject(status: "completed")`
### 7. Project Started ( Info) ### 7. Project Started ( Info)
**When:** Project status changes to in_progress **When:** Project status changes to in_progress
**Who Notified:** Project owner **Who Notified:** Project owner
**Format:** `⏱️ Project Started: {name}` - "You've started working on this" **Format:** `⏱️ Project Started: {name}` - "You've started working on this"
**Service:** `aethexProjectService.updateProject(status: "in_progress")` **Service:** `aethexProjectService.updateProject(status: "in_progress")`
### 8. Level Up (✅ Success) ### 8. Level Up (✅ Success)
**When:** User gains enough XP to level up **When:** User gains enough XP to level up
**Who Notified:** User **Who Notified:** User
**Format:** `⬆️ Level Up!` - "You've reached level {n}!" **Format:** `⬆️ Level Up!` - "You've reached level {n}!"
**Service:** `aethexAchievementService.updateUserXPAndLevel()` **Service:** `aethexAchievementService.updateUserXPAndLevel()`
### 9. Onboarding Complete (✅ Success) ### 9. Onboarding Complete (✅ Success)
**When:** User finishes onboarding **When:** User finishes onboarding
**Who Notified:** User **Who Notified:** User
**Format:** `🎉 Welcome to AeThex!` - "Profile setup complete!" **Format:** `🎉 Welcome to AeThex!` - "Profile setup complete!"
**Service:** `Onboarding.tsx -> finishOnboarding()` **Service:** `Onboarding.tsx -> finishOnboarding()`
### 10. Account Linked (✅ Success) ### 10. Account Linked (✅ Success)
**When:** User links OAuth provider (Discord, GitHub, etc.) **When:** User links OAuth provider (Discord, GitHub, etc.)
**Who Notified:** User **Who Notified:** User
**Format:** `🔗 Account Linked: {provider}` - "Successfully linked" **Format:** `🔗 Account Linked: {provider}` - "Successfully linked"
**Service:** OAuth callback endpoints **Service:** OAuth callback endpoints
### 11. Email Verified (✅ Success) ### 11. Email Verified (✅ Success)
**When:** User verifies email **When:** User verifies email
**Who Notified:** User **Who Notified:** User
**Format:** `✉️ Email Verified` - "Your email has been verified" **Format:** `✉️ Email Verified` - "Your email has been verified"
**Service:** Auth flow (future implementation) **Service:** Auth flow (future implementation)
### 12. Post Liked ( Info) ### 12. Post Liked ( Info)
**When:** Someone likes a community post **When:** Someone likes a community post
**Who Notified:** Post author **Who Notified:** Post author
**Format:** `❤️ Your post was liked` - "{liker} liked your post" **Format:** `❤️ Your post was liked` - "{liker} liked your post"
@ -80,6 +92,7 @@ A comprehensive notification system covering 15+ user interactions across social
**Service:** `notificationTriggers.postLiked()` **Service:** `notificationTriggers.postLiked()`
### 13. Post Commented ( Info) ### 13. Post Commented ( Info)
**When:** Someone comments on a community post **When:** Someone comments on a community post
**Who Notified:** Post author **Who Notified:** Post author
**Format:** `💬 New comment on your post` - "{commenter} commented: {preview}" **Format:** `💬 New comment on your post` - "{commenter} commented: {preview}"
@ -87,27 +100,32 @@ A comprehensive notification system covering 15+ user interactions across social
**Service:** `notificationTriggers.postCommented()` **Service:** `notificationTriggers.postCommented()`
### 14. Endorsement Received (✅ Success) ### 14. Endorsement Received (✅ Success)
**When:** User endorses another user's skill **When:** User endorses another user's skill
**Who Notified:** Endorsed user **Who Notified:** Endorsed user
**Format:** `🎖️ New endorsement` - "{endorser} endorsed you for {skill}" **Format:** `🎖️ New endorsement` - "{endorser} endorsed you for {skill}"
**Endpoint:** `POST /api/social/endorse` **Endpoint:** `POST /api/social/endorse`
### 15. New Follower ( Info) ### 15. New Follower ( Info)
**When:** Someone follows a user **When:** Someone follows a user
**Who Notified:** Followed user **Who Notified:** Followed user
**Format:** `👥 New follower` - "{follower} started following you" **Format:** `👥 New follower` - "{follower} started following you"
**Endpoint:** `POST /api/social/follow` **Endpoint:** `POST /api/social/follow`
### 16. Task Assigned ( Info) ### 16. Task Assigned ( Info)
**When:** Task is assigned to user **When:** Task is assigned to user
**Who Notified:** Assignee **Who Notified:** Assignee
**Format:** `📋 Task assigned to you` - "{assigner} assigned: {title}" **Format:** `📋 Task assigned to you` - "{assigner} assigned: {title}"
**Endpoints:** **Endpoints:**
- `POST /api/tasks` (on create with assignee) - `POST /api/tasks` (on create with assignee)
- `PUT /api/tasks/:id/assign` - `PUT /api/tasks/:id/assign`
**Service:** `notificationTriggers.taskAssigned()` **Service:** `notificationTriggers.taskAssigned()`
### 17. Application Received ( Info) ### 17. Application Received ( Info)
**When:** Creator applies for an opportunity **When:** Creator applies for an opportunity
**Who Notified:** Opportunity poster **Who Notified:** Opportunity poster
**Format:** `📋 New Application: {title}` - "{creator} applied" **Format:** `📋 New Application: {title}` - "{creator} applied"
@ -115,6 +133,7 @@ A comprehensive notification system covering 15+ user interactions across social
**Service:** `notificationTriggers.applicationReceived()` **Service:** `notificationTriggers.applicationReceived()`
### 18. Application Status Changed (✅/❌ Success/Error) ### 18. Application Status Changed (✅/❌ Success/Error)
**When:** Application is accepted/rejected **When:** Application is accepted/rejected
**Who Notified:** Applicant **Who Notified:** Applicant
**Format:** `✅/❌ Application {status}` - "{message}" **Format:** `✅/❌ Application {status}` - "{message}"
@ -122,6 +141,7 @@ A comprehensive notification system covering 15+ user interactions across social
**Service:** `notificationTriggers.applicationStatusChanged()` **Service:** `notificationTriggers.applicationStatusChanged()`
### 19. New Device Login (⚠️ Warning) ### 19. New Device Login (⚠️ Warning)
**When:** User logs in from new device **When:** User logs in from new device
**Who Notified:** User **Who Notified:** User
**Format:** `🔐 New device login detected` - "New login from {device}. If this wasn't you, secure your account." **Format:** `🔐 New device login detected` - "New login from {device}. If this wasn't you, secure your account."
@ -129,6 +149,7 @@ A comprehensive notification system covering 15+ user interactions across social
**Service:** `notificationTriggers.newDeviceLogin()` **Service:** `notificationTriggers.newDeviceLogin()`
### 20. Moderation Report (⚠️ Warning) ### 20. Moderation Report (⚠️ Warning)
**When:** User submits moderation report **When:** User submits moderation report
**Who Notified:** All staff/moderators **Who Notified:** All staff/moderators
**Format:** `🚨 New moderation report` - "A {type} report has been submitted" **Format:** `🚨 New moderation report` - "A {type} report has been submitted"
@ -137,27 +158,30 @@ A comprehensive notification system covering 15+ user interactions across social
## Notification Types ## Notification Types
| Type | Color | Icon | Use Cases | | Type | Color | Icon | Use Cases |
|------|-------|------|-----------| | --------- | --------- | ---- | ------------------------------------------- |
| `success` | 🟢 Green | ✅ | Achievements, completion, account actions | | `success` | 🟢 Green | ✅ | Achievements, completion, account actions |
| `info` | 🔵 Blue | | Team/project updates, social interactions | | `info` | 🔵 Blue | | Team/project updates, social interactions |
| `warning` | 🟡 Yellow | ⚠️ | Security alerts, moderation reports | | `warning` | 🟡 Yellow | ⚠️ | Security alerts, moderation reports |
| `error` | 🔴 Red | ❌ | Rejections, failed actions, security issues | | `error` | 🔴 Red | ❌ | Rejections, failed actions, security issues |
## Integration Points ## Integration Points
### Client Services ### Client Services
- `code/client/lib/aethex-database-adapter.ts` - Project, achievement, profile notifications - `code/client/lib/aethex-database-adapter.ts` - Project, achievement, profile notifications
- `code/client/lib/aethex-collab-service.ts` - Team/project member notifications - `code/client/lib/aethex-collab-service.ts` - Team/project member notifications
- `code/client/lib/notification-triggers.ts` - Centralized trigger utilities - `code/client/lib/notification-triggers.ts` - Centralized trigger utilities
- `code/client/pages/Onboarding.tsx` - Onboarding completion notification - `code/client/pages/Onboarding.tsx` - Onboarding completion notification
### Server Endpoints ### Server Endpoints
- `code/server/index.ts` - Social, community, task, application, moderation, auth endpoints - `code/server/index.ts` - Social, community, task, application, moderation, auth endpoints
- `code/api/discord/oauth/callback.ts` - Account linking notifications - `code/api/discord/oauth/callback.ts` - Account linking notifications
- `code/api/_notifications.ts` - Backend notification helper utilities - `code/api/_notifications.ts` - Backend notification helper utilities
### Database ### Database
- `notifications` table - Stores all notifications - `notifications` table - Stores all notifications
- `user_follows` - Follow notifications - `user_follows` - Follow notifications
- `community_post_likes` - Like notifications - `community_post_likes` - Like notifications
@ -179,6 +203,7 @@ A comprehensive notification system covering 15+ user interactions across social
## How Notifications Are Created ## How Notifications Are Created
### Pattern 1: Direct Insert (Server Endpoints) ### Pattern 1: Direct Insert (Server Endpoints)
```javascript ```javascript
await adminSupabase.from("notifications").insert({ await adminSupabase.from("notifications").insert({
user_id: targetUserId, user_id: targetUserId,
@ -189,16 +214,18 @@ await adminSupabase.from("notifications").insert({
``` ```
### Pattern 2: Service Method (Client Services) ### Pattern 2: Service Method (Client Services)
```javascript ```javascript
await aethexNotificationService.createNotification( await aethexNotificationService.createNotification(
userId, userId,
"success", "success",
"Title", "Title",
"Message" "Message",
); );
``` ```
### Pattern 3: Trigger Utilities (Client) ### Pattern 3: Trigger Utilities (Client)
```javascript ```javascript
await notificationTriggers.postLiked(userId, likerName); await notificationTriggers.postLiked(userId, likerName);
``` ```
@ -214,6 +241,7 @@ await notificationTriggers.postLiked(userId, likerName);
## Notification Display ## Notification Display
**NotificationBell Component** (`code/client/components/notifications/NotificationBell.tsx`) **NotificationBell Component** (`code/client/components/notifications/NotificationBell.tsx`)
- Bell icon with unread count badge - Bell icon with unread count badge
- Dropdown showing latest notifications - Dropdown showing latest notifications
- Type-specific icons (emoji-based) - Type-specific icons (emoji-based)
@ -221,6 +249,7 @@ await notificationTriggers.postLiked(userId, likerName);
- Real-time update via Supabase subscription - Real-time update via Supabase subscription
**Dashboard Tab** (`code/client/pages/Dashboard.tsx`) **Dashboard Tab** (`code/client/pages/Dashboard.tsx`)
- Full notification history - Full notification history
- Type filtering options - Type filtering options
- Batch actions (mark as read) - Batch actions (mark as read)
@ -228,6 +257,7 @@ await notificationTriggers.postLiked(userId, likerName);
## Testing Notifications ## Testing Notifications
### Manual Testing Checklist ### Manual Testing Checklist
- [ ] Create team/project → notification - [ ] Create team/project → notification
- [ ] Get added to team/project → notification - [ ] Get added to team/project → notification
- [ ] Like community post → post author notified - [ ] Like community post → post author notified
@ -242,18 +272,19 @@ await notificationTriggers.postLiked(userId, likerName);
- [ ] Link Discord → user notified - [ ] Link Discord → user notified
### Database Verification ### Database Verification
```sql ```sql
-- Check notifications for user -- Check notifications for user
SELECT * FROM notifications SELECT * FROM notifications
WHERE user_id = '...' WHERE user_id = '...'
ORDER BY created_at DESC ORDER BY created_at DESC
LIMIT 20; LIMIT 20;
-- Check notification types -- Check notification types
SELECT type, COUNT(*) FROM notifications GROUP BY type; SELECT type, COUNT(*) FROM notifications GROUP BY type;
-- Check unread count -- Check unread count
SELECT COUNT(*) FROM notifications SELECT COUNT(*) FROM notifications
WHERE user_id = '...' AND read = false; WHERE user_id = '...' AND read = false;
``` ```
@ -272,6 +303,7 @@ WHERE user_id = '...' AND read = false;
## Monitoring ## Monitoring
Check in Supabase dashboard: Check in Supabase dashboard:
1. `notifications` table → see all notifications 1. `notifications` table → see all notifications
2. Real-time → verify subscriptions active 2. Real-time → verify subscriptions active
3. Database stats → monitor table growth 3. Database stats → monitor table growth
@ -280,31 +312,34 @@ Check in Supabase dashboard:
## Support & Troubleshooting ## Support & Troubleshooting
**Notifications not showing?** **Notifications not showing?**
1. Check NotificationBell is rendered in Layout.tsx 1. Check NotificationBell is rendered in Layout.tsx
2. Verify Supabase subscription in browser console 2. Verify Supabase subscription in browser console
3. Check notifications table for entries 3. Check notifications table for entries
4. Clear browser cache and reload 4. Clear browser cache and reload
**Real-time not working?** **Real-time not working?**
1. Check Supabase realtime enabled 1. Check Supabase realtime enabled
2. Verify WebSocket connection in browser DevTools 2. Verify WebSocket connection in browser DevTools
3. Check RLS policies allow reading notifications 3. Check RLS policies allow reading notifications
4. Restart browser and clear session 4. Restart browser and clear session
**Spam notifications?** **Spam notifications?**
1. Check for duplicate inserts 1. Check for duplicate inserts
2. Verify notification triggers have `try-catch` 2. Verify notification triggers have `try-catch`
3. Add deduplication logic (check for recent identical notifications) 3. Add deduplication logic (check for recent identical notifications)
## Files Summary ## Files Summary
| File | Purpose | Lines | | File | Purpose | Lines |
|------|---------|-------| | ----------------------------------------------------------- | ----------------------------------- | ----- |
| `code/server/index.ts` | Server endpoints with notifications | 4800+ | | `code/server/index.ts` | Server endpoints with notifications | 4800+ |
| `code/client/lib/notification-triggers.ts` | Trigger utilities | 250+ | | `code/client/lib/notification-triggers.ts` | Trigger utilities | 250+ |
| `code/client/lib/aethex-database-adapter.ts` | Service notifications | 2000+ | | `code/client/lib/aethex-database-adapter.ts` | Service notifications | 2000+ |
| `code/client/components/notifications/NotificationBell.tsx` | UI display | 300+ | | `code/client/components/notifications/NotificationBell.tsx` | UI display | 300+ |
| `code/api/_notifications.ts` | Backend helpers | 40+ | | `code/api/_notifications.ts` | Backend helpers | 40+ |
**Total Notification Triggers: 20+** **Total Notification Triggers: 20+**
**Notification Types: 4** (success, info, warning, error) **Notification Types: 4** (success, info, warning, error)

View file

@ -14,51 +14,61 @@ The notification system has been comprehensively implemented to provide real-tim
### Client-Side Services ### Client-Side Services
#### 1. `code/client/lib/aethex-database-adapter.ts` #### 1. `code/client/lib/aethex-database-adapter.ts`
**Achievement Notifications** **Achievement Notifications**
- Modified `aethexAchievementService.awardAchievement()`: - Modified `aethexAchievementService.awardAchievement()`:
- Sends notification: `🏆 Achievement Unlocked: {name}` with XP reward - Sends notification: `🏆 Achievement Unlocked: {name}` with XP reward
- Type: "success" - Type: "success"
**Profile Update Notifications** **Profile Update Notifications**
- Modified `aethexUserService.updateProfile()`: - Modified `aethexUserService.updateProfile()`:
- Sends notification when `onboarded: true` - Sends notification when `onboarded: true`
- Message: `🎉 Welcome to AeThex! You've completed your profile setup. Let's get started!` - Message: `🎉 Welcome to AeThex! You've completed your profile setup. Let's get started!`
- Type: "success" - Type: "success"
**Level Up Notifications** **Level Up Notifications**
- Modified `aethexAchievementService.updateUserXPAndLevel()`: - Modified `aethexAchievementService.updateUserXPAndLevel()`:
- Sends notification when level increases - Sends notification when level increases
- Message: `⬆️ Level Up! You've reached level {newLevel}!` - Message: `⬆️ Level Up! You've reached level {newLevel}!`
- Type: "success" - Type: "success"
**Project Notifications** **Project Notifications**
- Modified `aethexProjectService.createProject()`: - Modified `aethexProjectService.createProject()`:
- Sends notification: `🚀 Project Created: {name}` - Sends notification: `🚀 Project Created: {name}`
- Type: "success" - Type: "success"
- Modified `aethexProjectService.updateProject()`: - Modified `aethexProjectService.updateProject()`:
- Sends notification on completion: `✅ Project Completed: {name}` - Sends notification on completion: `✅ Project Completed: {name}`
- Sends notification on start: `⏱️ Project Started: {name}` - Sends notification on start: `⏱️ Project Started: {name}`
- Type: "success" or "info" - Type: "success" or "info"
#### 2. `code/client/lib/aethex-collab-service.ts` #### 2. `code/client/lib/aethex-collab-service.ts`
**Team Notifications** **Team Notifications**
- Modified `aethexCollabService.createTeam()`: - Modified `aethexCollabService.createTeam()`:
- Sends notification: `🎯 Team Created: {name}` - Sends notification: `🎯 Team Created: {name}`
- Type: "success" - Type: "success"
**Team Member Notifications** **Team Member Notifications**
- Modified `aethexCollabService.addTeamMember()`: - Modified `aethexCollabService.addTeamMember()`:
- Sends notification: `👥 Added to Team: {name}` - Sends notification: `👥 Added to Team: {name}`
- Type: "info" - Type: "info"
**Project Member Notifications** **Project Member Notifications**
- Modified `aethexCollabService.addProjectMember()`: - Modified `aethexCollabService.addProjectMember()`:
- Sends notification: `📌 Added to Project: {name}` - Sends notification: `📌 Added to Project: {name}`
- Type: "info" - Type: "info"
#### 3. `code/client/pages/Onboarding.tsx` #### 3. `code/client/pages/Onboarding.tsx`
**Onboarding Notifications** **Onboarding Notifications**
- Added notification on onboarding completion - Added notification on onboarding completion
- Message: `🎉 Welcome to AeThex! You've completed your profile setup. Let's get started!` - Message: `🎉 Welcome to AeThex! You've completed your profile setup. Let's get started!`
- Type: "success" - Type: "success"
@ -66,13 +76,17 @@ The notification system has been comprehensively implemented to provide real-tim
### Backend API Endpoints ### Backend API Endpoints
#### 1. `code/api/_notifications.ts` (NEW) #### 1. `code/api/_notifications.ts` (NEW)
Central notification utility for backend processes: Central notification utility for backend processes:
- `createNotification(userId, type, title, message)` - Generic notification creator - `createNotification(userId, type, title, message)` - Generic notification creator
- `notifyAccountLinked(userId, provider)` - For OAuth linking - `notifyAccountLinked(userId, provider)` - For OAuth linking
- `notifyOnboardingComplete(userId)` - For onboarding completion - `notifyOnboardingComplete(userId)` - For onboarding completion
#### 2. `code/api/discord/oauth/callback.ts` #### 2. `code/api/discord/oauth/callback.ts`
**Discord Account Linking** **Discord Account Linking**
- Added import: `notifyAccountLinked` from `_notifications` - Added import: `notifyAccountLinked` from `_notifications`
- Sends notification when Discord is linked (both linking and login flows) - Sends notification when Discord is linked (both linking and login flows)
- Message: `🔗 Account Linked: Discord` - Message: `🔗 Account Linked: Discord`
@ -81,26 +95,28 @@ Central notification utility for backend processes:
### Utility Module ### Utility Module
#### `code/client/lib/notification-triggers.ts` (NEW) #### `code/client/lib/notification-triggers.ts` (NEW)
Centralized notification trigger utilities for consistent notification handling across the app: Centralized notification trigger utilities for consistent notification handling across the app:
```typescript ```typescript
notificationTriggers.achievementUnlocked(userId, name, xp) notificationTriggers.achievementUnlocked(userId, name, xp);
notificationTriggers.teamCreated(userId, teamName) notificationTriggers.teamCreated(userId, teamName);
notificationTriggers.addedToTeam(userId, teamName, role) notificationTriggers.addedToTeam(userId, teamName, role);
notificationTriggers.projectCreated(userId, projectName) notificationTriggers.projectCreated(userId, projectName);
notificationTriggers.addedToProject(userId, projectName, role) notificationTriggers.addedToProject(userId, projectName, role);
notificationTriggers.projectCompleted(userId, projectName) notificationTriggers.projectCompleted(userId, projectName);
notificationTriggers.projectStarted(userId, projectName) notificationTriggers.projectStarted(userId, projectName);
notificationTriggers.levelUp(userId, newLevel) notificationTriggers.levelUp(userId, newLevel);
notificationTriggers.onboardingComplete(userId) notificationTriggers.onboardingComplete(userId);
notificationTriggers.accountLinked(userId, provider) notificationTriggers.accountLinked(userId, provider);
notificationTriggers.emailVerified(userId) notificationTriggers.emailVerified(userId);
notificationTriggers.customNotification(userId, type, title, message) notificationTriggers.customNotification(userId, type, title, message);
``` ```
## Notification Types ## Notification Types
### Success (Green) 🟢 ### Success (Green) 🟢
- Achievement unlocked - Achievement unlocked
- Team/project created - Team/project created
- Project completed - Project completed
@ -110,18 +126,22 @@ notificationTriggers.customNotification(userId, type, title, message)
- Email verified - Email verified
### Info (Blue) 🔵 ### Info (Blue) 🔵
- Added to team/project - Added to team/project
- Project started - Project started
### Warning (Yellow) 🟡 ### Warning (Yellow) 🟡
- (Available for future use) - (Available for future use)
### Error (Red) 🔴 ### Error (Red) 🔴
- (Available for future use) - (Available for future use)
## Real-Time Features ## Real-Time Features
All notifications are: All notifications are:
1. **Real-time** - Delivered via Supabase realtime subscription (in NotificationBell component) 1. **Real-time** - Delivered via Supabase realtime subscription (in NotificationBell component)
2. **Persistent** - Stored in `notifications` table with timestamps 2. **Persistent** - Stored in `notifications` table with timestamps
3. **Readable** - Users can mark notifications as read 3. **Readable** - Users can mark notifications as read
@ -130,7 +150,9 @@ All notifications are:
## Notification Display ## Notification Display
Notifications appear in: Notifications appear in:
1. **NotificationBell Component** (`code/client/components/notifications/NotificationBell.tsx`) 1. **NotificationBell Component** (`code/client/components/notifications/NotificationBell.tsx`)
- Dropdown with all notifications - Dropdown with all notifications
- Shows unread count badge - Shows unread count badge
- Real-time updates via subscription - Real-time updates via subscription
@ -146,23 +168,24 @@ Notifications appear in:
### When Notifications Are Created ### When Notifications Are Created
| Event | Service | Method | Type | | Event | Service | Method | Type |
|-------|---------|--------|------| | --------------------------- | ------------------------ | ---------------------- | ------- |
| Achievement earned | AethexAchievementService | awardAchievement() | success | | Achievement earned | AethexAchievementService | awardAchievement() | success |
| Team created | AethexCollabService | createTeam() | success | | Team created | AethexCollabService | createTeam() | success |
| User added to team | AethexCollabService | addTeamMember() | info | | User added to team | AethexCollabService | addTeamMember() | info |
| Project created | AethexProjectService | createProject() | success | | Project created | AethexProjectService | createProject() | success |
| User added to project | AethexCollabService | addProjectMember() | info | | User added to project | AethexCollabService | addProjectMember() | info |
| Project status: completed | AethexProjectService | updateProject() | success | | Project status: completed | AethexProjectService | updateProject() | success |
| Project status: in_progress | AethexProjectService | updateProject() | info | | Project status: in_progress | AethexProjectService | updateProject() | info |
| Level increased | AethexAchievementService | updateUserXPAndLevel() | success | | Level increased | AethexAchievementService | updateUserXPAndLevel() | success |
| Onboarding completed | Onboarding page | finishOnboarding() | success | | Onboarding completed | Onboarding page | finishOnboarding() | success |
| Discord linked | Discord OAuth | callback.ts | success | | Discord linked | Discord OAuth | callback.ts | success |
| Profile updated (onboarded) | AethexUserService | updateProfile() | success | | Profile updated (onboarded) | AethexUserService | updateProfile() | success |
## Error Handling ## Error Handling
All notification creation is **non-blocking**: All notification creation is **non-blocking**:
- Wrapped in try-catch blocks - Wrapped in try-catch blocks
- Logged to console if failures occur - Logged to console if failures occur
- Does not prevent main operation from completing - Does not prevent main operation from completing
@ -173,16 +196,19 @@ All notification creation is **non-blocking**:
Potential notification triggers for future implementation: Potential notification triggers for future implementation:
1. **Social Features** 1. **Social Features**
- New follower - New follower
- Post liked/commented - Post liked/commented
- Mentioned in post - Mentioned in post
2. **Collaboration** 2. **Collaboration**
- Task assigned - Task assigned
- Comment on project - Comment on project
- Team invitation - Team invitation
3. **Notifications** 3. **Notifications**
- Email verification needed - Email verification needed
- Session expiration warning - Session expiration warning
- Security alerts - Security alerts
@ -197,20 +223,24 @@ Potential notification triggers for future implementation:
### Manual Testing Steps ### Manual Testing Steps
1. **Achievement Notification** 1. **Achievement Notification**
- Go to Dashboard - Go to Dashboard
- Trigger an achievement (e.g., create first project for "Portfolio Creator") - Trigger an achievement (e.g., create first project for "Portfolio Creator")
- Check NotificationBell for 🏆 icon - Check NotificationBell for 🏆 icon
2. **Team Notification** 2. **Team Notification**
- Create a new team - Create a new team
- Check NotificationBell for 🎯 icon - Check NotificationBell for 🎯 icon
3. **Discord Linking** 3. **Discord Linking**
- Go to Dashboard > Connections - Go to Dashboard > Connections
- Link Discord account - Link Discord account
- Check NotificationBell for 🔗 icon - Check NotificationBell for 🔗 icon
4. **Onboarding Notification** 4. **Onboarding Notification**
- Sign up new account - Sign up new account
- Complete onboarding - Complete onboarding
- Should see 🎉 notification after finishing - Should see 🎉 notification after finishing
@ -223,6 +253,7 @@ Potential notification triggers for future implementation:
### Monitoring ### Monitoring
Check Supabase dashboard: Check Supabase dashboard:
- Navigate to `notifications` table - Navigate to `notifications` table
- Filter by user_id to see all notifications for a user - Filter by user_id to see all notifications for a user
- Verify type, title, message fields are populated correctly - Verify type, title, message fields are populated correctly
@ -276,6 +307,7 @@ CREATE INDEX notifications_user_created_idx ON notifications(user_id, created_at
## Support ## Support
For issues or questions about the notification system: For issues or questions about the notification system:
1. Check NotificationBell component for display issues 1. Check NotificationBell component for display issues
2. Check Supabase console for database errors 2. Check Supabase console for database errors
3. Check browser console for JavaScript errors 3. Check browser console for JavaScript errors

View file

@ -2802,7 +2802,10 @@ export function createServer() {
.eq("id", user_id) .eq("id", user_id)
.single(); .single();
const likerName = (liker as any)?.full_name || (liker as any)?.username || "Someone"; const likerName =
(liker as any)?.full_name ||
(liker as any)?.username ||
"Someone";
await adminSupabase.from("notifications").insert({ await adminSupabase.from("notifications").insert({
user_id: post.user_id, user_id: post.user_id,
type: "info", type: "info",
@ -2917,8 +2920,12 @@ export function createServer() {
.eq("id", user_id) .eq("id", user_id)
.single(); .single();
const commenterName = (commenter as any)?.full_name || (commenter as any)?.username || "Someone"; const commenterName =
const preview = content.substring(0, 50) + (content.length > 50 ? "..." : ""); (commenter as any)?.full_name ||
(commenter as any)?.username ||
"Someone";
const preview =
content.substring(0, 50) + (content.length > 50 ? "..." : "");
await adminSupabase.from("notifications").insert({ await adminSupabase.from("notifications").insert({
user_id: post.user_id, user_id: post.user_id,
type: "info", type: "info",
@ -4334,7 +4341,10 @@ export function createServer() {
message: `${creatorProfile?.full_name || "A creator"} applied for your opportunity.`, message: `${creatorProfile?.full_name || "A creator"} applied for your opportunity.`,
}); });
} catch (notifError) { } catch (notifError) {
console.warn("Failed to create application notification:", notifError); console.warn(
"Failed to create application notification:",
notifError,
);
} }
} }
@ -4409,14 +4419,31 @@ export function createServer() {
.single(); .single();
if (applicantProfile?.user_id) { if (applicantProfile?.user_id) {
const statusEmoji = status === "accepted" ? "✅" : status === "rejected" ? "❌" : "📝"; const statusEmoji =
const statusMessage = status === "accepted" ? "accepted" : status === "rejected" ? "rejected" : "updated"; status === "accepted"
? "✅"
: status === "rejected"
? "❌"
: "📝";
const statusMessage =
status === "accepted"
? "accepted"
: status === "rejected"
? "rejected"
: "updated";
await adminSupabase.from("notifications").insert({ await adminSupabase.from("notifications").insert({
user_id: applicantProfile.user_id, user_id: applicantProfile.user_id,
type: status === "accepted" ? "success" : status === "rejected" ? "error" : "info", type:
status === "accepted"
? "success"
: status === "rejected"
? "error"
: "info",
title: `${statusEmoji} Application ${statusMessage}`, title: `${statusEmoji} Application ${statusMessage}`,
message: response_message || `Your application has been ${statusMessage}.`, message:
response_message ||
`Your application has been ${statusMessage}.`,
}); });
} }
} catch (notifError) { } catch (notifError) {
@ -4646,10 +4673,19 @@ export function createServer() {
// Task assignment with notification // Task assignment with notification
app.post("/api/tasks", async (req, res) => { app.post("/api/tasks", async (req, res) => {
try { try {
const { project_id, title, description, assignee_id, due_date, user_id } = req.body; const {
project_id,
title,
description,
assignee_id,
due_date,
user_id,
} = req.body;
if (!project_id || !title || !user_id) { if (!project_id || !title || !user_id) {
return res.status(400).json({ error: "project_id, title, and user_id required" }); return res
.status(400)
.json({ error: "project_id, title, and user_id required" });
} }
const { data, error } = await adminSupabase const { data, error } = await adminSupabase
@ -4676,7 +4712,10 @@ export function createServer() {
.eq("id", user_id) .eq("id", user_id)
.single(); .single();
const assignerName = (assigner as any)?.full_name || (assigner as any)?.username || "Someone"; const assignerName =
(assigner as any)?.full_name ||
(assigner as any)?.username ||
"Someone";
await adminSupabase.from("notifications").insert({ await adminSupabase.from("notifications").insert({
user_id: assignee_id, user_id: assignee_id,
type: "info", type: "info",
@ -4702,7 +4741,9 @@ export function createServer() {
const { assignee_id, user_id } = req.body; const { assignee_id, user_id } = req.body;
if (!taskId || !assignee_id || !user_id) { if (!taskId || !assignee_id || !user_id) {
return res.status(400).json({ error: "task id, assignee_id, and user_id required" }); return res
.status(400)
.json({ error: "task id, assignee_id, and user_id required" });
} }
const { data: task } = await adminSupabase const { data: task } = await adminSupabase
@ -4732,7 +4773,10 @@ export function createServer() {
.eq("id", user_id) .eq("id", user_id)
.single(); .single();
const assignerName = (assigner as any)?.full_name || (assigner as any)?.username || "Someone"; const assignerName =
(assigner as any)?.full_name ||
(assigner as any)?.username ||
"Someone";
await adminSupabase.from("notifications").insert({ await adminSupabase.from("notifications").insert({
user_id: assignee_id, user_id: assignee_id,
type: "info", type: "info",
@ -4753,10 +4797,15 @@ export function createServer() {
// Moderation report with staff notification // Moderation report with staff notification
app.post("/api/moderation/reports", async (req, res) => { app.post("/api/moderation/reports", async (req, res) => {
try { try {
const { reported_user_id, report_type, description, reporter_id } = req.body; const { reported_user_id, report_type, description, reporter_id } =
req.body;
if (!reported_user_id || !report_type || !reporter_id) { if (!reported_user_id || !report_type || !reporter_id) {
return res.status(400).json({ error: "reported_user_id, report_type, and reporter_id required" }); return res
.status(400)
.json({
error: "reported_user_id, report_type, and reporter_id required",
});
} }
const { data, error } = await adminSupabase const { data, error } = await adminSupabase