Prettier format pending files
This commit is contained in:
parent
77750af0da
commit
08c038b954
6 changed files with 250 additions and 76 deletions
|
|
@ -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(
|
||||
userId,
|
||||
"success",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
@ -542,7 +549,10 @@ export const aethexUserService = {
|
|||
"You've completed your profile setup. Let's get started!",
|
||||
);
|
||||
} 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) {
|
||||
console.warn("Failed to create project status notification:", notifError);
|
||||
console.warn(
|
||||
"Failed to create project status notification:",
|
||||
notifError,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
await aethexNotificationService.createNotification(
|
||||
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 {
|
||||
await aethexNotificationService.createNotification(
|
||||
userId,
|
||||
|
|
@ -155,13 +163,22 @@ export const notificationTriggers = {
|
|||
message: string,
|
||||
): Promise<void> {
|
||||
try {
|
||||
await aethexNotificationService.createNotification(userId, type, title, message);
|
||||
await aethexNotificationService.createNotification(
|
||||
userId,
|
||||
type,
|
||||
title,
|
||||
message,
|
||||
);
|
||||
} catch (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 {
|
||||
await aethexNotificationService.createNotification(
|
||||
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 {
|
||||
await aethexNotificationService.createNotification(
|
||||
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 {
|
||||
await aethexNotificationService.createNotification(
|
||||
userId,
|
||||
|
|
@ -218,13 +243,23 @@ export const notificationTriggers = {
|
|||
status: "accepted" | "rejected" | "reviewed",
|
||||
message?: string,
|
||||
): Promise<void> {
|
||||
const statusEmoji = status === "accepted" ? "✅" : status === "rejected" ? "❌" : "📝";
|
||||
const statusMessage = status === "accepted" ? "accepted" : status === "rejected" ? "rejected" : "reviewed";
|
||||
const statusEmoji =
|
||||
status === "accepted" ? "✅" : status === "rejected" ? "❌" : "📝";
|
||||
const statusMessage =
|
||||
status === "accepted"
|
||||
? "accepted"
|
||||
: status === "rejected"
|
||||
? "rejected"
|
||||
: "reviewed";
|
||||
|
||||
try {
|
||||
await aethexNotificationService.createNotification(
|
||||
userId,
|
||||
status === "accepted" ? "success" : status === "rejected" ? "error" : "info",
|
||||
status === "accepted"
|
||||
? "success"
|
||||
: status === "rejected"
|
||||
? "error"
|
||||
: "info",
|
||||
`${statusEmoji} Application ${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 {
|
||||
await aethexNotificationService.createNotification(
|
||||
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 {
|
||||
await aethexNotificationService.createNotification(
|
||||
userId,
|
||||
|
|
|
|||
|
|
@ -7,72 +7,84 @@ A comprehensive notification system covering 15+ user interactions across social
|
|||
## All Notification Flows
|
||||
|
||||
### 1. Achievements (✅ Success)
|
||||
|
||||
**When:** User earns an achievement
|
||||
**Who Notified:** Achievement earner
|
||||
**Format:** `🏆 Achievement Unlocked: {name}` - "{xp} XP awarded"
|
||||
**Service:** `aethexAchievementService.awardAchievement()`
|
||||
|
||||
### 2. Team Creation (✅ Success)
|
||||
|
||||
**When:** Team is created
|
||||
**Who Notified:** Team creator
|
||||
**Format:** `🎯 Team Created: {name}` - "Your team is ready to go!"
|
||||
**Service:** `aethexCollabService.createTeam()`
|
||||
|
||||
### 3. Added to Team (ℹ️ Info)
|
||||
|
||||
**When:** User is added to a team
|
||||
**Who Notified:** New team member
|
||||
**Format:** `👥 Added to Team: {name}` - "You've been added as a {role}"
|
||||
**Service:** `aethexCollabService.addTeamMember()`
|
||||
|
||||
### 4. Project Creation (✅ Success)
|
||||
|
||||
**When:** Project is created
|
||||
**Who Notified:** Project creator
|
||||
**Format:** `🚀 Project Created: {name}` - "Your project is ready to go!"
|
||||
**Service:** `aethexProjectService.createProject()`
|
||||
|
||||
### 5. Added to Project (ℹ️ Info)
|
||||
|
||||
**When:** User is added to a project
|
||||
**Who Notified:** New project member
|
||||
**Format:** `📌 Added to Project: {name}` - "You've been added as a {role}"
|
||||
**Service:** `aethexCollabService.addProjectMember()`
|
||||
|
||||
### 6. Project Completed (✅ Success)
|
||||
|
||||
**When:** Project status changes to completed
|
||||
**Who Notified:** Project owner
|
||||
**Format:** `✅ Project Completed: {name}` - "Congratulations!"
|
||||
**Service:** `aethexProjectService.updateProject(status: "completed")`
|
||||
|
||||
### 7. Project Started (ℹ️ Info)
|
||||
|
||||
**When:** Project status changes to in_progress
|
||||
**Who Notified:** Project owner
|
||||
**Format:** `⏱️ Project Started: {name}` - "You've started working on this"
|
||||
**Service:** `aethexProjectService.updateProject(status: "in_progress")`
|
||||
|
||||
### 8. Level Up (✅ Success)
|
||||
|
||||
**When:** User gains enough XP to level up
|
||||
**Who Notified:** User
|
||||
**Format:** `⬆️ Level Up!` - "You've reached level {n}!"
|
||||
**Service:** `aethexAchievementService.updateUserXPAndLevel()`
|
||||
|
||||
### 9. Onboarding Complete (✅ Success)
|
||||
|
||||
**When:** User finishes onboarding
|
||||
**Who Notified:** User
|
||||
**Format:** `🎉 Welcome to AeThex!` - "Profile setup complete!"
|
||||
**Service:** `Onboarding.tsx -> finishOnboarding()`
|
||||
|
||||
### 10. Account Linked (✅ Success)
|
||||
|
||||
**When:** User links OAuth provider (Discord, GitHub, etc.)
|
||||
**Who Notified:** User
|
||||
**Format:** `🔗 Account Linked: {provider}` - "Successfully linked"
|
||||
**Service:** OAuth callback endpoints
|
||||
|
||||
### 11. Email Verified (✅ Success)
|
||||
|
||||
**When:** User verifies email
|
||||
**Who Notified:** User
|
||||
**Format:** `✉️ Email Verified` - "Your email has been verified"
|
||||
**Service:** Auth flow (future implementation)
|
||||
|
||||
### 12. Post Liked (ℹ️ Info)
|
||||
|
||||
**When:** Someone likes a community post
|
||||
**Who Notified:** Post author
|
||||
**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()`
|
||||
|
||||
### 13. Post Commented (ℹ️ Info)
|
||||
|
||||
**When:** Someone comments on a community post
|
||||
**Who Notified:** Post author
|
||||
**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()`
|
||||
|
||||
### 14. Endorsement Received (✅ Success)
|
||||
|
||||
**When:** User endorses another user's skill
|
||||
**Who Notified:** Endorsed user
|
||||
**Format:** `🎖️ New endorsement` - "{endorser} endorsed you for {skill}"
|
||||
**Endpoint:** `POST /api/social/endorse`
|
||||
|
||||
### 15. New Follower (ℹ️ Info)
|
||||
|
||||
**When:** Someone follows a user
|
||||
**Who Notified:** Followed user
|
||||
**Format:** `👥 New follower` - "{follower} started following you"
|
||||
**Endpoint:** `POST /api/social/follow`
|
||||
|
||||
### 16. Task Assigned (ℹ️ Info)
|
||||
|
||||
**When:** Task is assigned to user
|
||||
**Who Notified:** Assignee
|
||||
**Format:** `📋 Task assigned to you` - "{assigner} assigned: {title}"
|
||||
**Endpoints:**
|
||||
|
||||
- `POST /api/tasks` (on create with assignee)
|
||||
- `PUT /api/tasks/:id/assign`
|
||||
**Service:** `notificationTriggers.taskAssigned()`
|
||||
**Service:** `notificationTriggers.taskAssigned()`
|
||||
|
||||
### 17. Application Received (ℹ️ Info)
|
||||
|
||||
**When:** Creator applies for an opportunity
|
||||
**Who Notified:** Opportunity poster
|
||||
**Format:** `📋 New Application: {title}` - "{creator} applied"
|
||||
|
|
@ -115,6 +133,7 @@ A comprehensive notification system covering 15+ user interactions across social
|
|||
**Service:** `notificationTriggers.applicationReceived()`
|
||||
|
||||
### 18. Application Status Changed (✅/❌ Success/Error)
|
||||
|
||||
**When:** Application is accepted/rejected
|
||||
**Who Notified:** Applicant
|
||||
**Format:** `✅/❌ Application {status}` - "{message}"
|
||||
|
|
@ -122,6 +141,7 @@ A comprehensive notification system covering 15+ user interactions across social
|
|||
**Service:** `notificationTriggers.applicationStatusChanged()`
|
||||
|
||||
### 19. New Device Login (⚠️ Warning)
|
||||
|
||||
**When:** User logs in from new device
|
||||
**Who Notified:** User
|
||||
**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()`
|
||||
|
||||
### 20. Moderation Report (⚠️ Warning)
|
||||
|
||||
**When:** User submits moderation report
|
||||
**Who Notified:** All staff/moderators
|
||||
**Format:** `🚨 New moderation report` - "A {type} report has been submitted"
|
||||
|
|
@ -138,7 +159,7 @@ A comprehensive notification system covering 15+ user interactions across social
|
|||
## Notification Types
|
||||
|
||||
| Type | Color | Icon | Use Cases |
|
||||
|------|-------|------|-----------|
|
||||
| --------- | --------- | ---- | ------------------------------------------- |
|
||||
| `success` | 🟢 Green | ✅ | Achievements, completion, account actions |
|
||||
| `info` | 🔵 Blue | ℹ️ | Team/project updates, social interactions |
|
||||
| `warning` | 🟡 Yellow | ⚠️ | Security alerts, moderation reports |
|
||||
|
|
@ -147,17 +168,20 @@ A comprehensive notification system covering 15+ user interactions across social
|
|||
## Integration Points
|
||||
|
||||
### Client Services
|
||||
|
||||
- `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/notification-triggers.ts` - Centralized trigger utilities
|
||||
- `code/client/pages/Onboarding.tsx` - Onboarding completion notification
|
||||
|
||||
### Server Endpoints
|
||||
|
||||
- `code/server/index.ts` - Social, community, task, application, moderation, auth endpoints
|
||||
- `code/api/discord/oauth/callback.ts` - Account linking notifications
|
||||
- `code/api/_notifications.ts` - Backend notification helper utilities
|
||||
|
||||
### Database
|
||||
|
||||
- `notifications` table - Stores all notifications
|
||||
- `user_follows` - Follow notifications
|
||||
- `community_post_likes` - Like notifications
|
||||
|
|
@ -179,6 +203,7 @@ A comprehensive notification system covering 15+ user interactions across social
|
|||
## How Notifications Are Created
|
||||
|
||||
### Pattern 1: Direct Insert (Server Endpoints)
|
||||
|
||||
```javascript
|
||||
await adminSupabase.from("notifications").insert({
|
||||
user_id: targetUserId,
|
||||
|
|
@ -189,16 +214,18 @@ await adminSupabase.from("notifications").insert({
|
|||
```
|
||||
|
||||
### Pattern 2: Service Method (Client Services)
|
||||
|
||||
```javascript
|
||||
await aethexNotificationService.createNotification(
|
||||
userId,
|
||||
"success",
|
||||
"Title",
|
||||
"Message"
|
||||
"Message",
|
||||
);
|
||||
```
|
||||
|
||||
### Pattern 3: Trigger Utilities (Client)
|
||||
|
||||
```javascript
|
||||
await notificationTriggers.postLiked(userId, likerName);
|
||||
```
|
||||
|
|
@ -214,6 +241,7 @@ await notificationTriggers.postLiked(userId, likerName);
|
|||
## Notification Display
|
||||
|
||||
**NotificationBell Component** (`code/client/components/notifications/NotificationBell.tsx`)
|
||||
|
||||
- Bell icon with unread count badge
|
||||
- Dropdown showing latest notifications
|
||||
- Type-specific icons (emoji-based)
|
||||
|
|
@ -221,6 +249,7 @@ await notificationTriggers.postLiked(userId, likerName);
|
|||
- Real-time update via Supabase subscription
|
||||
|
||||
**Dashboard Tab** (`code/client/pages/Dashboard.tsx`)
|
||||
|
||||
- Full notification history
|
||||
- Type filtering options
|
||||
- Batch actions (mark as read)
|
||||
|
|
@ -228,6 +257,7 @@ await notificationTriggers.postLiked(userId, likerName);
|
|||
## Testing Notifications
|
||||
|
||||
### Manual Testing Checklist
|
||||
|
||||
- [ ] Create team/project → notification
|
||||
- [ ] Get added to team/project → notification
|
||||
- [ ] Like community post → post author notified
|
||||
|
|
@ -242,6 +272,7 @@ await notificationTriggers.postLiked(userId, likerName);
|
|||
- [ ] Link Discord → user notified
|
||||
|
||||
### Database Verification
|
||||
|
||||
```sql
|
||||
-- Check notifications for user
|
||||
SELECT * FROM notifications
|
||||
|
|
@ -272,6 +303,7 @@ WHERE user_id = '...' AND read = false;
|
|||
## Monitoring
|
||||
|
||||
Check in Supabase dashboard:
|
||||
|
||||
1. `notifications` table → see all notifications
|
||||
2. Real-time → verify subscriptions active
|
||||
3. Database stats → monitor table growth
|
||||
|
|
@ -280,18 +312,21 @@ Check in Supabase dashboard:
|
|||
## Support & Troubleshooting
|
||||
|
||||
**Notifications not showing?**
|
||||
|
||||
1. Check NotificationBell is rendered in Layout.tsx
|
||||
2. Verify Supabase subscription in browser console
|
||||
3. Check notifications table for entries
|
||||
4. Clear browser cache and reload
|
||||
|
||||
**Real-time not working?**
|
||||
|
||||
1. Check Supabase realtime enabled
|
||||
2. Verify WebSocket connection in browser DevTools
|
||||
3. Check RLS policies allow reading notifications
|
||||
4. Restart browser and clear session
|
||||
|
||||
**Spam notifications?**
|
||||
|
||||
1. Check for duplicate inserts
|
||||
2. Verify notification triggers have `try-catch`
|
||||
3. Add deduplication logic (check for recent identical notifications)
|
||||
|
|
@ -299,7 +334,7 @@ Check in Supabase dashboard:
|
|||
## Files Summary
|
||||
|
||||
| File | Purpose | Lines |
|
||||
|------|---------|-------|
|
||||
| ----------------------------------------------------------- | ----------------------------------- | ----- |
|
||||
| `code/server/index.ts` | Server endpoints with notifications | 4800+ |
|
||||
| `code/client/lib/notification-triggers.ts` | Trigger utilities | 250+ |
|
||||
| `code/client/lib/aethex-database-adapter.ts` | Service notifications | 2000+ |
|
||||
|
|
|
|||
|
|
@ -14,51 +14,61 @@ The notification system has been comprehensively implemented to provide real-tim
|
|||
### Client-Side Services
|
||||
|
||||
#### 1. `code/client/lib/aethex-database-adapter.ts`
|
||||
|
||||
**Achievement Notifications**
|
||||
|
||||
- Modified `aethexAchievementService.awardAchievement()`:
|
||||
- Sends notification: `🏆 Achievement Unlocked: {name}` with XP reward
|
||||
- Type: "success"
|
||||
|
||||
**Profile Update Notifications**
|
||||
|
||||
- Modified `aethexUserService.updateProfile()`:
|
||||
- Sends notification when `onboarded: true`
|
||||
- Message: `🎉 Welcome to AeThex! You've completed your profile setup. Let's get started!`
|
||||
- Type: "success"
|
||||
|
||||
**Level Up Notifications**
|
||||
|
||||
- Modified `aethexAchievementService.updateUserXPAndLevel()`:
|
||||
- Sends notification when level increases
|
||||
- Message: `⬆️ Level Up! You've reached level {newLevel}!`
|
||||
- Type: "success"
|
||||
|
||||
**Project Notifications**
|
||||
|
||||
- Modified `aethexProjectService.createProject()`:
|
||||
- Sends notification: `🚀 Project Created: {name}`
|
||||
- Type: "success"
|
||||
|
||||
- Modified `aethexProjectService.updateProject()`:
|
||||
- Sends notification on completion: `✅ Project Completed: {name}`
|
||||
- Sends notification on start: `⏱️ Project Started: {name}`
|
||||
- Type: "success" or "info"
|
||||
|
||||
#### 2. `code/client/lib/aethex-collab-service.ts`
|
||||
|
||||
**Team Notifications**
|
||||
|
||||
- Modified `aethexCollabService.createTeam()`:
|
||||
- Sends notification: `🎯 Team Created: {name}`
|
||||
- Type: "success"
|
||||
|
||||
**Team Member Notifications**
|
||||
|
||||
- Modified `aethexCollabService.addTeamMember()`:
|
||||
- Sends notification: `👥 Added to Team: {name}`
|
||||
- Type: "info"
|
||||
|
||||
**Project Member Notifications**
|
||||
|
||||
- Modified `aethexCollabService.addProjectMember()`:
|
||||
- Sends notification: `📌 Added to Project: {name}`
|
||||
- Type: "info"
|
||||
|
||||
#### 3. `code/client/pages/Onboarding.tsx`
|
||||
|
||||
**Onboarding Notifications**
|
||||
|
||||
- Added notification on onboarding completion
|
||||
- Message: `🎉 Welcome to AeThex! You've completed your profile setup. Let's get started!`
|
||||
- Type: "success"
|
||||
|
|
@ -66,13 +76,17 @@ The notification system has been comprehensively implemented to provide real-tim
|
|||
### Backend API Endpoints
|
||||
|
||||
#### 1. `code/api/_notifications.ts` (NEW)
|
||||
|
||||
Central notification utility for backend processes:
|
||||
|
||||
- `createNotification(userId, type, title, message)` - Generic notification creator
|
||||
- `notifyAccountLinked(userId, provider)` - For OAuth linking
|
||||
- `notifyOnboardingComplete(userId)` - For onboarding completion
|
||||
|
||||
#### 2. `code/api/discord/oauth/callback.ts`
|
||||
|
||||
**Discord Account Linking**
|
||||
|
||||
- Added import: `notifyAccountLinked` from `_notifications`
|
||||
- Sends notification when Discord is linked (both linking and login flows)
|
||||
- Message: `🔗 Account Linked: Discord`
|
||||
|
|
@ -81,26 +95,28 @@ Central notification utility for backend processes:
|
|||
### Utility Module
|
||||
|
||||
#### `code/client/lib/notification-triggers.ts` (NEW)
|
||||
|
||||
Centralized notification trigger utilities for consistent notification handling across the app:
|
||||
|
||||
```typescript
|
||||
notificationTriggers.achievementUnlocked(userId, name, xp)
|
||||
notificationTriggers.teamCreated(userId, teamName)
|
||||
notificationTriggers.addedToTeam(userId, teamName, role)
|
||||
notificationTriggers.projectCreated(userId, projectName)
|
||||
notificationTriggers.addedToProject(userId, projectName, role)
|
||||
notificationTriggers.projectCompleted(userId, projectName)
|
||||
notificationTriggers.projectStarted(userId, projectName)
|
||||
notificationTriggers.levelUp(userId, newLevel)
|
||||
notificationTriggers.onboardingComplete(userId)
|
||||
notificationTriggers.accountLinked(userId, provider)
|
||||
notificationTriggers.emailVerified(userId)
|
||||
notificationTriggers.customNotification(userId, type, title, message)
|
||||
notificationTriggers.achievementUnlocked(userId, name, xp);
|
||||
notificationTriggers.teamCreated(userId, teamName);
|
||||
notificationTriggers.addedToTeam(userId, teamName, role);
|
||||
notificationTriggers.projectCreated(userId, projectName);
|
||||
notificationTriggers.addedToProject(userId, projectName, role);
|
||||
notificationTriggers.projectCompleted(userId, projectName);
|
||||
notificationTriggers.projectStarted(userId, projectName);
|
||||
notificationTriggers.levelUp(userId, newLevel);
|
||||
notificationTriggers.onboardingComplete(userId);
|
||||
notificationTriggers.accountLinked(userId, provider);
|
||||
notificationTriggers.emailVerified(userId);
|
||||
notificationTriggers.customNotification(userId, type, title, message);
|
||||
```
|
||||
|
||||
## Notification Types
|
||||
|
||||
### Success (Green) 🟢
|
||||
|
||||
- Achievement unlocked
|
||||
- Team/project created
|
||||
- Project completed
|
||||
|
|
@ -110,18 +126,22 @@ notificationTriggers.customNotification(userId, type, title, message)
|
|||
- Email verified
|
||||
|
||||
### Info (Blue) 🔵
|
||||
|
||||
- Added to team/project
|
||||
- Project started
|
||||
|
||||
### Warning (Yellow) 🟡
|
||||
|
||||
- (Available for future use)
|
||||
|
||||
### Error (Red) 🔴
|
||||
|
||||
- (Available for future use)
|
||||
|
||||
## Real-Time Features
|
||||
|
||||
All notifications are:
|
||||
|
||||
1. **Real-time** - Delivered via Supabase realtime subscription (in NotificationBell component)
|
||||
2. **Persistent** - Stored in `notifications` table with timestamps
|
||||
3. **Readable** - Users can mark notifications as read
|
||||
|
|
@ -130,7 +150,9 @@ All notifications are:
|
|||
## Notification Display
|
||||
|
||||
Notifications appear in:
|
||||
|
||||
1. **NotificationBell Component** (`code/client/components/notifications/NotificationBell.tsx`)
|
||||
|
||||
- Dropdown with all notifications
|
||||
- Shows unread count badge
|
||||
- Real-time updates via subscription
|
||||
|
|
@ -147,7 +169,7 @@ Notifications appear in:
|
|||
### When Notifications Are Created
|
||||
|
||||
| Event | Service | Method | Type |
|
||||
|-------|---------|--------|------|
|
||||
| --------------------------- | ------------------------ | ---------------------- | ------- |
|
||||
| Achievement earned | AethexAchievementService | awardAchievement() | success |
|
||||
| Team created | AethexCollabService | createTeam() | success |
|
||||
| User added to team | AethexCollabService | addTeamMember() | info |
|
||||
|
|
@ -163,6 +185,7 @@ Notifications appear in:
|
|||
## Error Handling
|
||||
|
||||
All notification creation is **non-blocking**:
|
||||
|
||||
- Wrapped in try-catch blocks
|
||||
- Logged to console if failures occur
|
||||
- Does not prevent main operation from completing
|
||||
|
|
@ -173,16 +196,19 @@ All notification creation is **non-blocking**:
|
|||
Potential notification triggers for future implementation:
|
||||
|
||||
1. **Social Features**
|
||||
|
||||
- New follower
|
||||
- Post liked/commented
|
||||
- Mentioned in post
|
||||
|
||||
2. **Collaboration**
|
||||
|
||||
- Task assigned
|
||||
- Comment on project
|
||||
- Team invitation
|
||||
|
||||
3. **Notifications**
|
||||
|
||||
- Email verification needed
|
||||
- Session expiration warning
|
||||
- Security alerts
|
||||
|
|
@ -197,20 +223,24 @@ Potential notification triggers for future implementation:
|
|||
### Manual Testing Steps
|
||||
|
||||
1. **Achievement Notification**
|
||||
|
||||
- Go to Dashboard
|
||||
- Trigger an achievement (e.g., create first project for "Portfolio Creator")
|
||||
- Check NotificationBell for 🏆 icon
|
||||
|
||||
2. **Team Notification**
|
||||
|
||||
- Create a new team
|
||||
- Check NotificationBell for 🎯 icon
|
||||
|
||||
3. **Discord Linking**
|
||||
|
||||
- Go to Dashboard > Connections
|
||||
- Link Discord account
|
||||
- Check NotificationBell for 🔗 icon
|
||||
|
||||
4. **Onboarding Notification**
|
||||
|
||||
- Sign up new account
|
||||
- Complete onboarding
|
||||
- Should see 🎉 notification after finishing
|
||||
|
|
@ -223,6 +253,7 @@ Potential notification triggers for future implementation:
|
|||
### Monitoring
|
||||
|
||||
Check Supabase dashboard:
|
||||
|
||||
- Navigate to `notifications` table
|
||||
- Filter by user_id to see all notifications for a user
|
||||
- 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
|
||||
|
||||
For issues or questions about the notification system:
|
||||
|
||||
1. Check NotificationBell component for display issues
|
||||
2. Check Supabase console for database errors
|
||||
3. Check browser console for JavaScript errors
|
||||
|
|
|
|||
|
|
@ -2802,7 +2802,10 @@ export function createServer() {
|
|||
.eq("id", user_id)
|
||||
.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({
|
||||
user_id: post.user_id,
|
||||
type: "info",
|
||||
|
|
@ -2917,8 +2920,12 @@ export function createServer() {
|
|||
.eq("id", user_id)
|
||||
.single();
|
||||
|
||||
const commenterName = (commenter as any)?.full_name || (commenter as any)?.username || "Someone";
|
||||
const preview = content.substring(0, 50) + (content.length > 50 ? "..." : "");
|
||||
const commenterName =
|
||||
(commenter as any)?.full_name ||
|
||||
(commenter as any)?.username ||
|
||||
"Someone";
|
||||
const preview =
|
||||
content.substring(0, 50) + (content.length > 50 ? "..." : "");
|
||||
await adminSupabase.from("notifications").insert({
|
||||
user_id: post.user_id,
|
||||
type: "info",
|
||||
|
|
@ -4334,7 +4341,10 @@ export function createServer() {
|
|||
message: `${creatorProfile?.full_name || "A creator"} applied for your opportunity.`,
|
||||
});
|
||||
} 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();
|
||||
|
||||
if (applicantProfile?.user_id) {
|
||||
const statusEmoji = status === "accepted" ? "✅" : status === "rejected" ? "❌" : "📝";
|
||||
const statusMessage = status === "accepted" ? "accepted" : status === "rejected" ? "rejected" : "updated";
|
||||
const statusEmoji =
|
||||
status === "accepted"
|
||||
? "✅"
|
||||
: status === "rejected"
|
||||
? "❌"
|
||||
: "📝";
|
||||
const statusMessage =
|
||||
status === "accepted"
|
||||
? "accepted"
|
||||
: status === "rejected"
|
||||
? "rejected"
|
||||
: "updated";
|
||||
|
||||
await adminSupabase.from("notifications").insert({
|
||||
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}`,
|
||||
message: response_message || `Your application has been ${statusMessage}.`,
|
||||
message:
|
||||
response_message ||
|
||||
`Your application has been ${statusMessage}.`,
|
||||
});
|
||||
}
|
||||
} catch (notifError) {
|
||||
|
|
@ -4646,10 +4673,19 @@ export function createServer() {
|
|||
// Task assignment with notification
|
||||
app.post("/api/tasks", async (req, res) => {
|
||||
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) {
|
||||
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
|
||||
|
|
@ -4676,7 +4712,10 @@ export function createServer() {
|
|||
.eq("id", user_id)
|
||||
.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({
|
||||
user_id: assignee_id,
|
||||
type: "info",
|
||||
|
|
@ -4702,7 +4741,9 @@ export function createServer() {
|
|||
const { assignee_id, user_id } = req.body;
|
||||
|
||||
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
|
||||
|
|
@ -4732,7 +4773,10 @@ export function createServer() {
|
|||
.eq("id", user_id)
|
||||
.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({
|
||||
user_id: assignee_id,
|
||||
type: "info",
|
||||
|
|
@ -4753,10 +4797,15 @@ export function createServer() {
|
|||
// Moderation report with staff notification
|
||||
app.post("/api/moderation/reports", async (req, res) => {
|
||||
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) {
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in a new issue