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(
userId,
"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;
// 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,
);
}
}

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 {
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,

View file

@ -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()`
### 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+ |

View file

@ -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

View file

@ -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