aethex-forge/client/lib/supabase-service.ts
Builder.io c20613a8be Create Supabase service helpers
cgen-b271b1ef9e5a4a1a96416f389455706a
2025-08-06 00:04:05 +00:00

321 lines
8.1 KiB
TypeScript

import { supabase } from './supabase';
import type { Database, UserProfile, Project, Achievement, CommunityPost } from './database.types';
// User Profile Services
export const userProfileService = {
async getProfile(userId: string): Promise<UserProfile | null> {
const { data, error } = await supabase
.from('user_profiles')
.select('*')
.eq('id', userId)
.single();
if (error && error.code !== 'PGRST116') {
throw error;
}
return data;
},
async updateProfile(userId: string, updates: Partial<UserProfile>): Promise<UserProfile> {
const { data, error } = await supabase
.from('user_profiles')
.update(updates)
.eq('id', userId)
.select()
.single();
if (error) throw error;
return data;
},
async createProfile(profile: Omit<UserProfile, 'created_at' | 'updated_at'>): Promise<UserProfile> {
const { data, error } = await supabase
.from('user_profiles')
.insert(profile)
.select()
.single();
if (error) throw error;
return data;
},
async addInterests(userId: string, interests: string[]): Promise<void> {
const interestRows = interests.map(interest => ({
user_id: userId,
interest,
}));
const { error } = await supabase
.from('user_interests')
.insert(interestRows);
if (error) throw error;
},
async getUserInterests(userId: string): Promise<string[]> {
const { data, error } = await supabase
.from('user_interests')
.select('interest')
.eq('user_id', userId);
if (error) throw error;
return data.map(item => item.interest);
},
};
// Project Services
export const projectService = {
async getUserProjects(userId: string): Promise<Project[]> {
const { data, error } = await supabase
.from('projects')
.select('*')
.eq('user_id', userId)
.order('created_at', { ascending: false });
if (error) throw error;
return data;
},
async createProject(project: Omit<Project, 'id' | 'created_at' | 'updated_at'>): Promise<Project> {
const { data, error } = await supabase
.from('projects')
.insert(project)
.select()
.single();
if (error) throw error;
return data;
},
async updateProject(projectId: string, updates: Partial<Project>): Promise<Project> {
const { data, error } = await supabase
.from('projects')
.update(updates)
.eq('id', projectId)
.select()
.single();
if (error) throw error;
return data;
},
async deleteProject(projectId: string): Promise<void> {
const { error } = await supabase
.from('projects')
.delete()
.eq('id', projectId);
if (error) throw error;
},
async getAllProjects(limit = 10): Promise<Project[]> {
const { data, error } = await supabase
.from('projects')
.select(`
*,
user_profiles (
username,
full_name,
avatar_url
)
`)
.eq('status', 'completed')
.order('created_at', { ascending: false })
.limit(limit);
if (error) throw error;
return data;
},
};
// Achievement Services
export const achievementService = {
async getAllAchievements(): Promise<Achievement[]> {
const { data, error } = await supabase
.from('achievements')
.select('*')
.order('xp_reward', { ascending: false });
if (error) throw error;
return data;
},
async getUserAchievements(userId: string): Promise<Achievement[]> {
const { data, error } = await supabase
.from('user_achievements')
.select(`
earned_at,
achievements (*)
`)
.eq('user_id', userId)
.order('earned_at', { ascending: false });
if (error) throw error;
return data.map(item => item.achievements).filter(Boolean) as Achievement[];
},
async awardAchievement(userId: string, achievementId: string): Promise<void> {
const { error } = await supabase
.from('user_achievements')
.insert({
user_id: userId,
achievement_id: achievementId,
});
if (error && error.code !== '23505') { // Ignore duplicate key error
throw error;
}
},
async checkAndAwardAchievements(userId: string): Promise<void> {
// Check for various achievement conditions
const profile = await userProfileService.getProfile(userId);
const projects = await projectService.getUserProjects(userId);
if (!profile) return;
const achievements = await this.getAllAchievements();
// Welcome achievement
if (profile.full_name && profile.user_type) {
const welcomeAchievement = achievements.find(a => a.name === 'Welcome to AeThex');
if (welcomeAchievement) {
await this.awardAchievement(userId, welcomeAchievement.id);
}
}
// First project achievement
if (projects.length >= 1) {
const firstProjectAchievement = achievements.find(a => a.name === 'First Project');
if (firstProjectAchievement) {
await this.awardAchievement(userId, firstProjectAchievement.id);
}
}
// Experienced developer achievement
const completedProjects = projects.filter(p => p.status === 'completed');
if (completedProjects.length >= 5) {
const experiencedAchievement = achievements.find(a => a.name === 'Experienced Developer');
if (experiencedAchievement) {
await this.awardAchievement(userId, experiencedAchievement.id);
}
}
},
};
// Community Services
export const communityService = {
async getPosts(limit = 10): Promise<CommunityPost[]> {
const { data, error } = await supabase
.from('community_posts')
.select(`
*,
user_profiles (
username,
full_name,
avatar_url
)
`)
.eq('is_published', true)
.order('created_at', { ascending: false })
.limit(limit);
if (error) throw error;
return data;
},
async createPost(post: Omit<CommunityPost, 'id' | 'created_at' | 'updated_at' | 'likes_count' | 'comments_count'>): Promise<CommunityPost> {
const { data, error } = await supabase
.from('community_posts')
.insert(post)
.select()
.single();
if (error) throw error;
return data;
},
async getUserPosts(userId: string): Promise<CommunityPost[]> {
const { data, error } = await supabase
.from('community_posts')
.select('*')
.eq('author_id', userId)
.order('created_at', { ascending: false });
if (error) throw error;
return data;
},
};
// Notification Services
export const notificationService = {
async getUserNotifications(userId: string): Promise<any[]> {
const { data, error } = await supabase
.from('notifications')
.select('*')
.eq('user_id', userId)
.order('created_at', { ascending: false })
.limit(10);
if (error) throw error;
return data;
},
async markAsRead(notificationId: string): Promise<void> {
const { error } = await supabase
.from('notifications')
.update({ read: true })
.eq('id', notificationId);
if (error) throw error;
},
async createNotification(userId: string, title: string, message?: string, type = 'info'): Promise<void> {
const { error } = await supabase
.from('notifications')
.insert({
user_id: userId,
title,
message,
type,
});
if (error) throw error;
},
};
// Real-time subscriptions
export const realtimeService = {
subscribeToUserNotifications(userId: string, callback: (notification: any) => void) {
return supabase
.channel(`notifications:${userId}`)
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'notifications',
filter: `user_id=eq.${userId}`,
},
callback
)
.subscribe();
},
subscribeToCommunityPosts(callback: (post: any) => void) {
return supabase
.channel('community_posts')
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'community_posts',
filter: 'is_published=eq.true',
},
callback
)
.subscribe();
},
};