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 { 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, ): Promise { 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, ): Promise { 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 { 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 { 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 { 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, ): Promise { const { data, error } = await supabase .from("projects") .insert(project) .select() .single(); if (error) throw error; return data; }, async updateProject( projectId: string, updates: Partial, ): Promise { 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 { const { error } = await supabase .from("projects") .delete() .eq("id", projectId); if (error) throw error; }, async getAllProjects(limit = 10): Promise { 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 { const { data, error } = await supabase .from("achievements") .select("*") .order("xp_reward", { ascending: false }); if (error) throw error; return data; }, async getUserAchievements(userId: string): Promise { 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 { 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 { // 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 { 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 { const { data, error } = await supabase .from("community_posts") .insert(post) .select() .single(); if (error) throw error; return data; }, async getUserPosts(userId: string): Promise { 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 { 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 { 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 { 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(); }, };