diff --git a/apps/frontend/src/app/components/header/header.component.ts b/apps/frontend/src/app/components/header/header.component.ts
index 7d35d54..ba10b71 100644
--- a/apps/frontend/src/app/components/header/header.component.ts
+++ b/apps/frontend/src/app/components/header/header.component.ts
@@ -58,6 +58,7 @@ import { ApiService } from '../../services/api.service';
class="dropdown-menu"
role="menu"
aria-label="User menu"
+ tabindex="-1"
(keydown.escape)="closeDropdown()"
>
My Profile
diff --git a/shared-types/src/lib/achievement.constants.ts b/shared-types/src/lib/achievement.constants.ts
index 63b3fe7..fcbf485 100644
--- a/shared-types/src/lib/achievement.constants.ts
+++ b/shared-types/src/lib/achievement.constants.ts
@@ -5,72 +5,178 @@
*/
import {
AchievementCategory,
- AchievementDefinition,
+ type AchievementDefinition,
AchievementTier,
} from "./achievement.types";
export const ACHIEVEMENTS: Record = {
- // ========== SUGGESTION ACHIEVEMENTS (15) ==========
- suggestion_first_steps: {
- key: "suggestion_first_steps",
- title: "First Steps",
- description: "Submit your first 10 suggestions to the library",
- category: AchievementCategory.Suggestion,
- tier: AchievementTier.Bronze,
- icon: "🌱",
- points: 50,
- requirements: { count: 10 },
+
+ suggestion_approved: {
+ category: AchievementCategory.Suggestion,
+ description: "Have your first suggestion accepted",
+ icon: "✅",
+ key: "suggestion_approved",
+ points: 50,
+ requirements: { count: 1 },
+ title: "Approved!",
+ tier: AchievementTier.Bronze,
},
+
suggestion_contributor: {
- key: "suggestion_contributor",
- title: "Contributor",
- description: "Submit 50 suggestions to the library",
- category: AchievementCategory.Suggestion,
- tier: AchievementTier.Silver,
- icon: "📝",
- points: 100,
+ category: AchievementCategory.Suggestion,
+ description: "Submit 50 suggestions to the library",
+ icon: "📝",
+ key: "suggestion_contributor",
+ points: 100,
requirements: { count: 50 },
+ tier: AchievementTier.Silver,
+ title: "Contributor",
},
+
suggestion_dedicated: {
- key: "suggestion_dedicated",
- title: "Dedicated",
- description: "Submit 100 suggestions to the library",
- category: AchievementCategory.Suggestion,
- tier: AchievementTier.Gold,
- icon: "⭐",
- points: 250,
+ category: AchievementCategory.Suggestion,
+ description: "Submit 100 suggestions to the library",
+ icon: "⭐",
+ key: "suggestion_dedicated",
+ points: 250,
requirements: { count: 100 },
+ tier: AchievementTier.Gold,
+ title: "Dedicated",
},
- suggestion_master: {
- key: "suggestion_master",
- title: "Master Curator",
- description: "Submit 250 suggestions to the library",
- category: AchievementCategory.Suggestion,
+
+ suggestion_acceptance_100: {
+ key: "suggestion_acceptance_100",
+ description: "Achieve 100% acceptance rate (minimum 10 suggestions)",
+ title: "Perfect Record",
+ category: AchievementCategory.Suggestion,
+ icon: "✨",
tier: AchievementTier.Platinum,
- icon: "💎",
- points: 500,
- requirements: { count: 250 },
+ points: 500,
+ requirements: { count: 10, rate: 1.0 },
+ },
+ // ========== SUGGESTION ACHIEVEMENTS (15) ==========
+suggestion_first_steps: {
+ category: AchievementCategory.Suggestion,
+ description: "Submit your first 10 suggestions to the library",
+ icon: "🌱",
+ key: "suggestion_first_steps",
+ points: 50,
+ requirements: { count: 10 },
+ tier: AchievementTier.Bronze,
+ title: "First Steps",
+ },
+ suggestion_acceptance_75: {
+ description: "Maintain a 75%+ acceptance rate (minimum 20 suggestions)",
+ key: "suggestion_acceptance_75",
+ category: AchievementCategory.Suggestion,
+ title: "Quality Over Quantity",
+ icon: "🎯",
+ points: 300,
+ tier: AchievementTier.Gold,
+ requirements: { count: 20, rate: 0.75 },
},
suggestion_legend: {
- key: "suggestion_legend",
- title: "Legend",
- description: "Submit 500 suggestions to the library",
- category: AchievementCategory.Suggestion,
- tier: AchievementTier.Diamond,
- icon: "👑",
- points: 1000,
+ category: AchievementCategory.Suggestion,
+ description: "Submit 500 suggestions to the library",
+ icon: "👑",
+ key: "suggestion_legend",
+ points: 1000,
requirements: { count: 500 },
+ tier: AchievementTier.Diamond,
+ title: "Legend",
},
- suggestion_approved: {
- key: "suggestion_approved",
- title: "Approved!",
- description: "Have your first suggestion accepted",
- category: AchievementCategory.Suggestion,
+ like_enthusiast: {
+ key: "like_enthusiast",
+ description: "Like 25 items in the library",
+ title: "Enthusiast",
+ category: AchievementCategory.Like,
+ icon: "💕",
tier: AchievementTier.Bronze,
- icon: "✅",
- points: 50,
- requirements: { count: 1 },
+ points: 50,
+ requirements: { count: 25 },
},
+ suggestion_master: {
+ category: AchievementCategory.Suggestion,
+ description: "Submit 250 suggestions to the library",
+ icon: "💎",
+ key: "suggestion_master",
+ points: 500,
+ requirements: { count: 250 },
+ title: "Master Curator",
+ tier: AchievementTier.Platinum,
+ },
+ like_fan: {
+ description: "Like 100 items in the library",
+ key: "like_fan",
+ category: AchievementCategory.Like,
+ title: "Fan",
+ icon: "💖",
+ points: 100,
+ tier: AchievementTier.Silver,
+ requirements: { count: 100 },
+ },
+ suggestion_quality_10: {
+ category: AchievementCategory.Suggestion,
+ description: "Have 10 suggestions accepted",
+ icon: "🏆",
+ key: "suggestion_quality_10",
+ points: 200,
+ requirements: { count: 10 },
+ title: "Elite Curator",
+ tier: AchievementTier.Gold,
+ },
+ suggestion_enthusiast: {
+ description: "Submit 5 suggestions in one day",
+ category: AchievementCategory.Suggestion,
+ key: "suggestion_enthusiast",
+ icon: "🔥",
+ title: "Suggestion Enthusiast",
+ points: 150,
+ requirements: { count: 5, dayRange: 1 },
+ tier: AchievementTier.Silver,
+ },
+ suggestion_quality_100: {
+ description: "Have 100 suggestions accepted",
+ key: "suggestion_quality_100",
+ category: AchievementCategory.Suggestion,
+ title: "Ultimate Curator",
+ icon: "👸",
+ points: 1500,
+ tier: AchievementTier.Diamond,
+ requirements: { count: 100 },
+ },
+ like_book_lover: {
+ description: "Like 50 books",
+ key: "like_book_lover",
+ category: AchievementCategory.Like,
+ title: "Book Lover",
+ icon: "📚",
+ points: 100,
+ tier: AchievementTier.Silver,
+ requirements: { count: 50 },
+ },
+ suggestion_quality_25: {
+ description: "Have 25 suggestions accepted",
+ key: "suggestion_quality_25",
+ category: AchievementCategory.Suggestion,
+ title: "Master Curator",
+ icon: "💫",
+ points: 400,
+ tier: AchievementTier.Platinum,
+ requirements: { count: 25 },
+ },
+
+ like_cinephile: {
+ description: "Like 50 shows/films",
+ key: "like_cinephile",
+ category: AchievementCategory.Like,
+ title: "Cinephile",
+ icon: "🎬",
+ points: 100,
+ tier: AchievementTier.Silver,
+ requirements: { count: 50 },
+ },
+
suggestion_quality_5: {
key: "suggestion_quality_5",
title: "Quality Curator",
@@ -81,27 +187,32 @@ export const ACHIEVEMENTS: Record = {
points: 100,
requirements: { count: 5 },
},
- suggestion_quality_10: {
- key: "suggestion_quality_10",
- title: "Elite Curator",
- description: "Have 10 suggestions accepted",
- category: AchievementCategory.Suggestion,
+
+ like_diverse: {
+ description: "Like items from all 6 media types",
+ key: "like_diverse",
+ category: AchievementCategory.Like,
+ title: "Diverse Taste",
+ icon: "🌍",
+ points: 200,
tier: AchievementTier.Gold,
- icon: "🏆",
- points: 200,
- requirements: { count: 10 },
+ requirements: { diversity: true },
},
- suggestion_quality_25: {
- key: "suggestion_quality_25",
- title: "Master Curator",
- description: "Have 25 suggestions accepted",
- category: AchievementCategory.Suggestion,
- tier: AchievementTier.Platinum,
- icon: "💫",
- points: 400,
- requirements: { count: 25 },
+
+ // ========== COMMENT ACHIEVEMENTS (12) ==========
+comment_first: {
+ key: "comment_first",
+ description: "Leave your first comment in the library",
+ title: "First Thoughts",
+ category: AchievementCategory.Comment,
+ icon: "💬",
+ tier: AchievementTier.Bronze,
+ points: 25,
+ requirements: { count: 1 },
},
- suggestion_quality_50: {
+
+
+suggestion_quality_50: {
key: "suggestion_quality_50",
title: "Grand Master",
description: "Have 50 suggestions accepted",
@@ -111,167 +222,176 @@ export const ACHIEVEMENTS: Record = {
points: 700,
requirements: { count: 50 },
},
- suggestion_quality_100: {
- key: "suggestion_quality_100",
- title: "Ultimate Curator",
- description: "Have 100 suggestions accepted",
- category: AchievementCategory.Suggestion,
- tier: AchievementTier.Diamond,
- icon: "👸",
- points: 1500,
- requirements: { count: 100 },
- },
- suggestion_acceptance_75: {
- key: "suggestion_acceptance_75",
- title: "Quality Over Quantity",
- description: "Maintain a 75%+ acceptance rate (minimum 20 suggestions)",
- category: AchievementCategory.Suggestion,
- tier: AchievementTier.Gold,
- icon: "🎯",
- points: 300,
- requirements: { rate: 0.75, count: 20 },
- },
- suggestion_acceptance_100: {
- key: "suggestion_acceptance_100",
- title: "Perfect Record",
- description: "Achieve 100% acceptance rate (minimum 10 suggestions)",
- category: AchievementCategory.Suggestion,
- tier: AchievementTier.Platinum,
- icon: "✨",
- points: 500,
- requirements: { rate: 1.0, count: 10 },
+
+ comment_critic: {
+ key: "comment_critic",
+ description: "Leave 50 comments in the library",
+ title: "Critic",
+ category: AchievementCategory.Comment,
+ icon: "🗣️",
+ tier: AchievementTier.Silver,
+ points: 100,
+ requirements: { count: 50 },
},
+
+
suggestion_renaissance: {
- key: "suggestion_renaissance",
- title: "Renaissance Person",
description: "Submit accepted suggestions across all 6 media types",
- category: AchievementCategory.Suggestion,
+ key: "suggestion_renaissance",
+ category: AchievementCategory.Suggestion,
+ title: "Renaissance Person",
+ icon: "🌈",
+ points: 400,
tier: AchievementTier.Gold,
- icon: "🌈",
- points: 400,
requirements: { diversity: true },
},
- suggestion_enthusiast: {
- key: "suggestion_enthusiast",
- title: "Suggestion Enthusiast",
- description: "Submit 5 suggestions in one day",
- category: AchievementCategory.Suggestion,
- tier: AchievementTier.Silver,
- icon: "🔥",
- points: 150,
- requirements: { count: 5, dayRange: 1 },
+
+
+comment_expert: {
+ description: "Leave 100 comments in the library",
+ key: "comment_expert",
+ category: AchievementCategory.Comment,
+ title: "Expert Critic",
+ icon: "🎭",
+ points: 250,
+ tier: AchievementTier.Gold,
+ requirements: { count: 100 },
},
// ========== LIKE ACHIEVEMENTS (12) ==========
- like_first: {
- key: "like_first",
- title: "First Like",
+like_first: {
description: "Like your first item in the library",
- category: AchievementCategory.Like,
+ key: "like_first",
+ category: AchievementCategory.Like,
+ title: "First Like",
+ icon: "❤️",
+ points: 25,
tier: AchievementTier.Bronze,
- icon: "❤️",
- points: 25,
requirements: { count: 1 },
},
- like_enthusiast: {
- key: "like_enthusiast",
- title: "Enthusiast",
- description: "Like 25 items in the library",
- category: AchievementCategory.Like,
- tier: AchievementTier.Bronze,
- icon: "💕",
- points: 50,
- requirements: { count: 25 },
- },
- like_fan: {
- key: "like_fan",
- title: "Fan",
- description: "Like 100 items in the library",
- category: AchievementCategory.Like,
- tier: AchievementTier.Silver,
- icon: "💖",
- points: 100,
- requirements: { count: 100 },
- },
- like_super_fan: {
- key: "like_super_fan",
- title: "Super Fan",
- description: "Like 250 items in the library",
- category: AchievementCategory.Like,
- tier: AchievementTier.Gold,
- icon: "💝",
- points: 250,
- requirements: { count: 250 },
- },
- like_mega_fan: {
- key: "like_mega_fan",
- title: "Mega Fan",
- description: "Like 500 items in the library",
- category: AchievementCategory.Like,
- tier: AchievementTier.Platinum,
- icon: "💗",
- points: 500,
+
+ comment_legend: {
+ description: "Leave 500 comments in the library",
+ key: "comment_legend",
+ category: AchievementCategory.Comment,
+ title: "Review Legend",
+ icon: "🏅",
+ points: 1000,
+ tier: AchievementTier.Diamond,
requirements: { count: 500 },
},
+
+ like_mega_fan: {
+ description: "Like 500 items in the library",
+ key: "like_mega_fan",
+ category: AchievementCategory.Like,
+ title: "Mega Fan",
+ icon: "💗",
+ points: 500,
+ tier: AchievementTier.Platinum,
+ requirements: { count: 500 },
+ },
+
+ comment_detailed: {
+ description: "Write 10 comments with 500+ characters",
+ category: AchievementCategory.Comment,
+ key: "comment_detailed",
+ icon: "📝",
+ title: "Detailed Critic",
+ points: 150,
+ requirements: { count: 10 },
+ tier: AchievementTier.Silver,
+ },
+
+ like_super_fan: {
+ key: "like_super_fan",
+ description: "Like 250 items in the library",
+ title: "Super Fan",
+ category: AchievementCategory.Like,
+ icon: "💝",
+ tier: AchievementTier.Gold,
+ points: 250,
+ requirements: { count: 250 },
+ },
+ comment_essay: {
+ category: AchievementCategory.Comment,
+ description: "Write 5 comments with 1000+ characters",
+ icon: "📄",
+ key: "comment_essay",
+ points: 300,
+ title: "Essay Writer",
+ requirements: { count: 5 },
+ tier: AchievementTier.Gold,
+ },
like_legendary: {
- key: "like_legendary",
- title: "Legendary Fan",
+ key: "like_legendary",
description: "Like 1000 items in the library",
- category: AchievementCategory.Like,
- tier: AchievementTier.Diamond,
+ title: "Legendary Fan",
+ category: AchievementCategory.Like,
icon: "💞",
- points: 1000,
+ tier: AchievementTier.Diamond,
+ points: 1000,
requirements: { count: 1000 },
},
- like_book_lover: {
- key: "like_book_lover",
- title: "Book Lover",
- description: "Like 50 books",
- category: AchievementCategory.Like,
- tier: AchievementTier.Silver,
- icon: "📚",
- points: 100,
- requirements: { count: 50 },
+ comment_diverse: {
+ description: "Comment on all 6 media types",
+ category: AchievementCategory.Comment,
+ key: "comment_diverse",
+ icon: "🎨",
+ title: "Well-Rounded Critic",
+ points: 250,
+ requirements: { diversity: true },
+ tier: AchievementTier.Gold,
},
like_gamer: {
- key: "like_gamer",
- title: "Gamer",
+ key: "like_gamer",
description: "Like 50 games",
- category: AchievementCategory.Like,
- tier: AchievementTier.Silver,
+ title: "Gamer",
+ category: AchievementCategory.Like,
icon: "🎮",
- points: 100,
+ tier: AchievementTier.Silver,
+ points: 100,
requirements: { count: 50 },
},
- like_cinephile: {
- key: "like_cinephile",
- title: "Cinephile",
- description: "Like 50 shows/films",
- category: AchievementCategory.Like,
- tier: AchievementTier.Silver,
- icon: "🎬",
- points: 100,
- requirements: { count: 50 },
+ comment_first_to_comment: {
+ category: AchievementCategory.Comment,
+ description: "Be the first to comment on 10 items",
+ icon: "🗨️",
+ key: "comment_first_to_comment",
+ points: 200,
+ title: "Discussion Starter",
+ requirements: { count: 10 },
+ tier: AchievementTier.Silver,
},
like_music: {
- key: "like_music",
- title: "Music Enthusiast",
+ key: "like_music",
description: "Like 50 music albums",
- category: AchievementCategory.Like,
- tier: AchievementTier.Silver,
+ title: "Music Enthusiast",
+ category: AchievementCategory.Like,
icon: "🎵",
- points: 100,
+ tier: AchievementTier.Silver,
+ points: 100,
requirements: { count: 50 },
},
- like_diverse: {
- key: "like_diverse",
- title: "Diverse Taste",
- description: "Like items from all 6 media types",
- category: AchievementCategory.Like,
- tier: AchievementTier.Gold,
- icon: "🌍",
- points: 200,
- requirements: { diversity: true },
+ comment_master: {
+ description: "Leave 250 comments in the library",
+ category: AchievementCategory.Comment,
+ key: "comment_master",
+ icon: "📖",
+ title: "Master Reviewer",
+ points: 500,
+ requirements: { count: 250 },
+ tier: AchievementTier.Platinum,
+ },
+ comment_novel: {
+ category: AchievementCategory.Comment,
+ description: "Write 3 comments with 2000+ characters",
+ icon: "📚",
+ key: "comment_novel",
+ points: 500,
+ requirements: { count: 3 },
+ tier: AchievementTier.Platinum,
+ title: "Novel Writer",
},
like_binge: {
key: "like_binge",
@@ -283,131 +403,138 @@ export const ACHIEVEMENTS: Record = {
points: 150,
requirements: { count: 20, dayRange: 1 },
},
-
- // ========== COMMENT ACHIEVEMENTS (12) ==========
- comment_first: {
- key: "comment_first",
- title: "First Thoughts",
- description: "Leave your first comment in the library",
- category: AchievementCategory.Comment,
- tier: AchievementTier.Bronze,
- icon: "💬",
- points: 25,
- requirements: { count: 1 },
- },
comment_reviewer: {
- key: "comment_reviewer",
- title: "Reviewer",
+ key: "comment_reviewer",
description: "Leave 10 comments in the library",
- category: AchievementCategory.Comment,
- tier: AchievementTier.Bronze,
+ title: "Reviewer",
+ category: AchievementCategory.Comment,
icon: "✍️",
- points: 50,
+ tier: AchievementTier.Bronze,
+ points: 50,
requirements: { count: 10 },
},
- comment_critic: {
- key: "comment_critic",
- title: "Critic",
- description: "Leave 50 comments in the library",
- category: AchievementCategory.Comment,
- tier: AchievementTier.Silver,
- icon: "🗣️",
- points: 100,
- requirements: { count: 50 },
- },
- comment_expert: {
- key: "comment_expert",
- title: "Expert Critic",
- description: "Leave 100 comments in the library",
- category: AchievementCategory.Comment,
- tier: AchievementTier.Gold,
- icon: "🎭",
- points: 250,
- requirements: { count: 100 },
- },
- comment_master: {
- key: "comment_master",
- title: "Master Reviewer",
- description: "Leave 250 comments in the library",
- category: AchievementCategory.Comment,
- tier: AchievementTier.Platinum,
- icon: "📖",
- points: 500,
- requirements: { count: 250 },
- },
- comment_legend: {
- key: "comment_legend",
- title: "Review Legend",
- description: "Leave 500 comments in the library",
- category: AchievementCategory.Comment,
- tier: AchievementTier.Diamond,
- icon: "🏅",
- points: 1000,
- requirements: { count: 500 },
- },
- comment_detailed: {
- key: "comment_detailed",
- title: "Detailed Critic",
- description: "Write 10 comments with 500+ characters",
- category: AchievementCategory.Comment,
- tier: AchievementTier.Silver,
- icon: "📝",
- points: 150,
- requirements: { count: 10 },
- },
- comment_essay: {
- key: "comment_essay",
- title: "Essay Writer",
- description: "Write 5 comments with 1000+ characters",
- category: AchievementCategory.Comment,
- tier: AchievementTier.Gold,
- icon: "📄",
- points: 300,
- requirements: { count: 5 },
- },
- comment_novel: {
- key: "comment_novel",
- title: "Novel Writer",
- description: "Write 3 comments with 2000+ characters",
- category: AchievementCategory.Comment,
- tier: AchievementTier.Platinum,
- icon: "📚",
- points: 500,
- requirements: { count: 3 },
- },
comment_thoughtful: {
- key: "comment_thoughtful",
- title: "Thoughtful Reviewer",
- description: "Comment on 50 different items",
- category: AchievementCategory.Comment,
- tier: AchievementTier.Silver,
- icon: "💭",
- points: 150,
+ category: AchievementCategory.Comment,
+ description: "Comment on 50 different items",
+ icon: "💭",
+ key: "comment_thoughtful",
+ points: 150,
requirements: { uniqueItems: 50 },
- },
- comment_diverse: {
- key: "comment_diverse",
- title: "Well-Rounded Critic",
- description: "Comment on all 6 media types",
- category: AchievementCategory.Comment,
- tier: AchievementTier.Gold,
- icon: "🎨",
- points: 250,
- requirements: { diversity: true },
- },
- comment_first_to_comment: {
- key: "comment_first_to_comment",
- title: "Discussion Starter",
- description: "Be the first to comment on 10 items",
- category: AchievementCategory.Comment,
- tier: AchievementTier.Silver,
- icon: "🗨️",
- points: 200,
- requirements: { count: 10 },
+ tier: AchievementTier.Silver,
+ title: "Thoughtful Reviewer",
},
+ engagement_early_adopter: {
+ description: "Be among the first 10 users to join",
+ category: AchievementCategory.Engagement,
+ key: "engagement_early_adopter",
+ icon: "🌟",
+ title: "Early Adopter",
+ points: 1000,
+ requirements: {},
+ tier: AchievementTier.Diamond,
+ },
+
+ engagement_power_user: {
+ description: "Achieve Triple Threat 10 times",
+ category: AchievementCategory.Engagement,
+ key: "engagement_power_user",
+ icon: "💫",
+ title: "Power User",
+ points: 750,
+ requirements: { count: 10 },
+ tier: AchievementTier.Platinum,
+ },
+
+ engagement_founding_100: {
+ category: AchievementCategory.Engagement,
+ description: "Be among the first 100 users to join",
+ icon: "🎖️",
+ key: "engagement_founding_100",
+ points: 500,
+ title: "Founding Member",
+ requirements: {},
+ tier: AchievementTier.Gold,
+ },
+
+ engagement_streak_100: {
+ category: AchievementCategory.Engagement,
+ description: "Login for 100 days in a row",
+ icon: "🏆",
+ key: "engagement_streak_100",
+ points: 500,
+ title: "Committed",
+ requirements: { streak: 100 },
+ tier: AchievementTier.Gold,
+ },
+
+ engagement_founding_1000: {
+ category: AchievementCategory.Engagement,
+ description: "Be among the first 1000 users to join",
+ icon: "🚀",
+ key: "engagement_founding_1000",
+ points: 200,
+ requirements: {},
+ title: "Pioneer",
+ tier: AchievementTier.Silver,
+ },
+
+ engagement_streak_30: {
+ description: "Login for 30 days in a row",
+ category: AchievementCategory.Engagement,
+ key: "engagement_streak_30",
+ icon: "💪",
+ title: "Dedicated",
+ points: 250,
+ requirements: { streak: 30 },
+ tier: AchievementTier.Silver,
+ },
+
+ engagement_streak_365: {
+ category: AchievementCategory.Engagement,
+ description: "Login for 365 days in a row",
+ icon: "⚡",
+ key: "engagement_streak_365",
+ points: 2000,
+ title: "Unstoppable",
+ requirements: { streak: 365 },
+ tier: AchievementTier.Diamond,
+ },
+
+ engagement_streak_7: {
+ description: "Login for 7 days in a row",
+ key: "engagement_streak_7",
+ category: AchievementCategory.Engagement,
+ title: "Daily Visitor",
+ icon: "🔥",
+ points: 100,
+ tier: AchievementTier.Bronze,
+ requirements: { streak: 7 },
+ },
+
+ engagement_triple_threat: {
+ category: AchievementCategory.Engagement,
+ description: "Submit a suggestion, like an item, and leave a comment in the same day",
+ icon: "🎯",
+ key: "engagement_triple_threat",
+ points: 200,
+ requirements: { dayRange: 1 },
+ title: "Triple Threat",
+ tier: AchievementTier.Silver,
+ },
+
+engagement_veteran_180: {
+ category: AchievementCategory.Engagement,
+ description: "Have an account for 6 months",
+ icon: "📅",
+ key: "engagement_veteran_180",
+ points: 150,
+ requirements: { dayRange: 180 },
+ tier: AchievementTier.Silver,
+ title: "Seasoned",
+ },
// ========== ENGAGEMENT ACHIEVEMENTS (15) ==========
- engagement_welcome: {
+engagement_welcome: {
key: "engagement_welcome",
title: "Welcome!",
description: "Complete your profile setup",
@@ -417,227 +544,133 @@ export const ACHIEVEMENTS: Record = {
points: 25,
requirements: {},
},
- engagement_streak_7: {
- key: "engagement_streak_7",
- title: "Daily Visitor",
- description: "Login for 7 days in a row",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Bronze,
- icon: "🔥",
- points: 100,
- requirements: { streak: 7 },
- },
- engagement_streak_30: {
- key: "engagement_streak_30",
- title: "Dedicated",
- description: "Login for 30 days in a row",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Silver,
- icon: "💪",
- points: 250,
- requirements: { streak: 30 },
- },
- engagement_streak_100: {
- key: "engagement_streak_100",
- title: "Committed",
- description: "Login for 100 days in a row",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Gold,
- icon: "🏆",
- points: 500,
- requirements: { streak: 100 },
- },
- engagement_streak_365: {
- key: "engagement_streak_365",
- title: "Unstoppable",
- description: "Login for 365 days in a row",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Diamond,
- icon: "⚡",
- points: 2000,
- requirements: { streak: 365 },
- },
- engagement_triple_threat: {
- key: "engagement_triple_threat",
- title: "Triple Threat",
- description: "Submit a suggestion, like an item, and leave a comment in the same day",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Silver,
- icon: "🎯",
- points: 200,
- requirements: { dayRange: 1 },
- },
- engagement_power_user: {
- key: "engagement_power_user",
- title: "Power User",
- description: "Achieve Triple Threat 10 times",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Platinum,
- icon: "💫",
- points: 750,
- requirements: { count: 10 },
- },
- engagement_early_adopter: {
- key: "engagement_early_adopter",
- title: "Early Adopter",
- description: "Be among the first 10 users to join",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Diamond,
- icon: "🌟",
- points: 1000,
- requirements: {},
- },
- engagement_founding_100: {
- key: "engagement_founding_100",
- title: "Founding Member",
- description: "Be among the first 100 users to join",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Gold,
- icon: "🎖️",
- points: 500,
- requirements: {},
- },
- engagement_founding_1000: {
- key: "engagement_founding_1000",
- title: "Pioneer",
- description: "Be among the first 1000 users to join",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Silver,
- icon: "🚀",
- points: 200,
- requirements: {},
+ engagement_veteran_1825: {
+ category: AchievementCategory.Engagement,
+ description: "Have an account for 5 years",
+ icon: "🌠",
+ key: "engagement_veteran_1825",
+ points: 1500,
+ requirements: { dayRange: 1825 },
+ tier: AchievementTier.Diamond,
+ title: "Legend",
},
engagement_veteran_30: {
- key: "engagement_veteran_30",
- title: "Veteran",
- description: "Have an account for 30 days",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Bronze,
- icon: "⏰",
- points: 50,
+ category: AchievementCategory.Engagement,
+ description: "Have an account for 30 days",
+ icon: "⏰",
+ key: "engagement_veteran_30",
+ points: 50,
requirements: { dayRange: 30 },
- },
- engagement_veteran_180: {
- key: "engagement_veteran_180",
- title: "Seasoned",
- description: "Have an account for 6 months",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Silver,
- icon: "📅",
- points: 150,
- requirements: { dayRange: 180 },
+ tier: AchievementTier.Bronze,
+ title: "Veteran",
},
engagement_veteran_365: {
- key: "engagement_veteran_365",
- title: "Longstanding",
- description: "Have an account for 1 year",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Gold,
- icon: "🎂",
- points: 300,
+ category: AchievementCategory.Engagement,
+ description: "Have an account for 1 year",
+ icon: "🎂",
+ key: "engagement_veteran_365",
+ points: 300,
requirements: { dayRange: 365 },
+ tier: AchievementTier.Gold,
+ title: "Longstanding",
},
engagement_veteran_730: {
- key: "engagement_veteran_730",
- title: "Elder",
- description: "Have an account for 2 years",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Platinum,
- icon: "🗓️",
- points: 600,
+ category: AchievementCategory.Engagement,
+ description: "Have an account for 2 years",
+ icon: "🗓️",
+ key: "engagement_veteran_730",
+ points: 600,
requirements: { dayRange: 730 },
- },
- engagement_veteran_1825: {
- key: "engagement_veteran_1825",
- title: "Legend",
- description: "Have an account for 5 years",
- category: AchievementCategory.Engagement,
- tier: AchievementTier.Diamond,
- icon: "🌠",
- points: 1500,
- requirements: { dayRange: 1825 },
+ tier: AchievementTier.Platinum,
+ title: "Elder",
},
+ report_accuracy_80: {
+ category: AchievementCategory.Report,
+ description: "Maintain 80%+ ACTION_TAKEN rate (minimum 10 reports)",
+ icon: "🎯",
+ key: "report_accuracy_80",
+ points: 300,
+ requirements: { count: 10, rate: 0.8 },
+ tier: AchievementTier.Gold,
+ title: "Sharp Eye",
+ },
+
+ report_accuracy_90: {
+ category: AchievementCategory.Report,
+ description: "Maintain 90%+ ACTION_TAKEN rate (minimum 10 reports)",
+ icon: "🦅",
+ key: "report_accuracy_90",
+ points: 500,
+ requirements: { count: 10, rate: 0.9 },
+ tier: AchievementTier.Platinum,
+ title: "Eagle Eye",
+ },
+
+ report_consistent: {
+ category: AchievementCategory.Report,
+ description: "Submit at least one report weekly for 4 weeks",
+ icon: "📆",
+ key: "report_consistent",
+ points: 200,
+ requirements: { count: 4 },
+ tier: AchievementTier.Silver,
+ title: "Consistent Guardian",
+ },
+
+ report_guardian: {
+ category: AchievementCategory.Report,
+ description: "Have 5 reports result in ACTION_TAKEN",
+ icon: "🛡️",
+ key: "report_guardian",
+ points: 100,
+ requirements: { count: 5 },
+ tier: AchievementTier.Silver,
+ title: "Guardian",
+ },
+
+ report_protector: {
+ category: AchievementCategory.Report,
+ description: "Have 10 reports result in ACTION_TAKEN",
+ icon: "⚔️",
+ key: "report_protector",
+ points: 250,
+ requirements: { count: 10 },
+ tier: AchievementTier.Gold,
+ title: "Protector",
+ },
+
+ report_vigilant: {
+ category: AchievementCategory.Report,
+ description: "Have 25 reports result in ACTION_TAKEN",
+ icon: "🔰",
+ key: "report_vigilant",
+ points: 500,
+ requirements: { count: 25 },
+ tier: AchievementTier.Platinum,
+ title: "Vigilant Protector",
+ },
+
+ report_volume: {
+ category: AchievementCategory.Report,
+ description: "Submit 50 reports (any status)",
+ icon: "📝",
+ key: "report_volume",
+ points: 150,
+ requirements: { count: 50 },
+ tier: AchievementTier.Silver,
+ title: "Dedicated Reporter",
+ },
// ========== REPORT ACHIEVEMENTS (8) ==========
report_watchful: {
- key: "report_watchful",
+ description: "Submit your first valid report (ACTION_TAKEN)",
+ category: AchievementCategory.Report,
+ key: "report_watchful",
+ icon: "👀",
title: "Watchful Eye",
- description: "Submit your first valid report (ACTION_TAKEN)",
- category: AchievementCategory.Report,
- tier: AchievementTier.Bronze,
- icon: "👀",
- points: 50,
+ points: 50,
requirements: { count: 1 },
- },
- report_guardian: {
- key: "report_guardian",
- title: "Guardian",
- description: "Have 5 reports result in ACTION_TAKEN",
- category: AchievementCategory.Report,
- tier: AchievementTier.Silver,
- icon: "🛡️",
- points: 100,
- requirements: { count: 5 },
- },
- report_protector: {
- key: "report_protector",
- title: "Protector",
- description: "Have 10 reports result in ACTION_TAKEN",
- category: AchievementCategory.Report,
- tier: AchievementTier.Gold,
- icon: "⚔️",
- points: 250,
- requirements: { count: 10 },
- },
- report_vigilant: {
- key: "report_vigilant",
- title: "Vigilant Protector",
- description: "Have 25 reports result in ACTION_TAKEN",
- category: AchievementCategory.Report,
- tier: AchievementTier.Platinum,
- icon: "🔰",
- points: 500,
- requirements: { count: 25 },
- },
- report_accuracy_80: {
- key: "report_accuracy_80",
- title: "Sharp Eye",
- description: "Maintain 80%+ ACTION_TAKEN rate (minimum 10 reports)",
- category: AchievementCategory.Report,
- tier: AchievementTier.Gold,
- icon: "🎯",
- points: 300,
- requirements: { rate: 0.8, count: 10 },
- },
- report_accuracy_90: {
- key: "report_accuracy_90",
- title: "Eagle Eye",
- description: "Maintain 90%+ ACTION_TAKEN rate (minimum 10 reports)",
- category: AchievementCategory.Report,
- tier: AchievementTier.Platinum,
- icon: "🦅",
- points: 500,
- requirements: { rate: 0.9, count: 10 },
- },
- report_consistent: {
- key: "report_consistent",
- title: "Consistent Guardian",
- description: "Submit at least one report weekly for 4 weeks",
- category: AchievementCategory.Report,
- tier: AchievementTier.Silver,
- icon: "📆",
- points: 200,
- requirements: { count: 4 },
- },
- report_volume: {
- key: "report_volume",
- title: "Dedicated Reporter",
- description: "Submit 50 reports (any status)",
- category: AchievementCategory.Report,
- tier: AchievementTier.Silver,
- icon: "📝",
- points: 150,
- requirements: { count: 50 },
+ tier: AchievementTier.Bronze,
},
};
diff --git a/shared-types/src/lib/achievement.types.ts b/shared-types/src/lib/achievement.types.ts
index 06968b7..7d08de0 100644
--- a/shared-types/src/lib/achievement.types.ts
+++ b/shared-types/src/lib/achievement.types.ts
@@ -21,50 +21,50 @@ export enum AchievementTier {
}
export interface AchievementRequirements {
- count?: number;
- rate?: number;
- streak?: number;
- diversity?: boolean;
+ count?: number;
+ rate?: number;
+ streak?: number;
+ diversity?: boolean;
uniqueItems?: number;
- dayRange?: number;
+ dayRange?: number;
}
export interface AchievementDefinition {
- key: string;
- title: string;
- description: string;
- category: AchievementCategory;
- tier: AchievementTier;
- icon: string;
- points: number;
+ key: string;
+ title: string;
+ description: string;
+ category: AchievementCategory;
+ tier: AchievementTier;
+ icon: string;
+ points: number;
requirements: AchievementRequirements;
}
export interface UserAchievement {
- id: string;
- userId: string;
+ id: string;
+ userId: string;
achievementKey: string;
- progress: number;
- earned: boolean;
- earnedAt?: Date;
- createdAt: Date;
- updatedAt: Date;
+ progress: number;
+ earned: boolean;
+ earnedAt?: Date;
+ createdAt: Date;
+ updatedAt: Date;
}
export interface AchievementProgress {
definition: AchievementDefinition;
- progress: number;
- earned: boolean;
- earnedAt?: Date;
+ progress: number;
+ earned: boolean;
+ earnedAt?: Date;
}
export interface UserAchievementSummary {
- totalPoints: number;
- totalEarned: number;
- recentAchievements: AchievementProgress[];
- progressByCategory: {
+ totalPoints: number;
+ totalEarned: number;
+ recentAchievements: Array;
+ progressByCategory: Array<{
category: AchievementCategory;
- earned: number;
- total: number;
- }[];
+ earned: number;
+ total: number;
+ }>;
}
diff --git a/shared-types/src/lib/activity.types.ts b/shared-types/src/lib/activity.types.ts
index b247828..8882970 100644
--- a/shared-types/src/lib/activity.types.ts
+++ b/shared-types/src/lib/activity.types.ts
@@ -30,39 +30,39 @@ interface BaseActivity {
}
interface SuggestionActivity extends BaseActivity {
- type: ActivityType.suggestion;
- entityType: string;
+ type: ActivityType.suggestion;
+ entityType: string;
suggestionTitle: string;
- status: string;
+ status: string;
}
interface LikeActivity extends BaseActivity {
- type: ActivityType.like;
- entityType: string;
- entityId: string;
+ type: ActivityType.like;
+ entityType: string;
+ entityId: string;
entityTitle: string;
}
interface CommentActivity extends BaseActivity {
- type: ActivityType.comment;
- entityType: string;
- entityId: string;
- entityTitle: string;
+ type: ActivityType.comment;
+ entityType: string;
+ entityId: string;
+ entityTitle: string;
commentPreview: string;
}
interface AchievementActivity extends BaseActivity {
- type: ActivityType.achievement;
- achievementKey: string;
- achievementName: string;
- achievementIcon: string;
+ type: ActivityType.achievement;
+ achievementKey: string;
+ achievementName: string;
+ achievementIcon: string;
achievementPoints: number;
}
type Activity = SuggestionActivity | LikeActivity | CommentActivity | AchievementActivity;
interface ActivityFeedResponse {
- activities: Activity[];
+ activities: Array;
total: number;
hasMore: boolean;
}
diff --git a/shared-types/src/lib/auth.types.ts b/shared-types/src/lib/auth.types.ts
index 59c9183..8fda2c2 100644
--- a/shared-types/src/lib/auth.types.ts
+++ b/shared-types/src/lib/auth.types.ts
@@ -34,9 +34,9 @@ interface User {
isAdmin: boolean;
isBanned: boolean;
inDiscord: boolean;
- isVip: boolean;
- isMod: boolean;
- isStaff: boolean;
+ isVip: boolean;
+ isMod: boolean;
+ isStaff: boolean;
}
interface JwtPayload {
diff --git a/shared-types/src/lib/comment.types.ts b/shared-types/src/lib/comment.types.ts
index 212e2ed..b5ba1b8 100644
--- a/shared-types/src/lib/comment.types.ts
+++ b/shared-types/src/lib/comment.types.ts
@@ -4,34 +4,34 @@
* @author Naomi Carrigan
*/
-import { PrimaryBadge } from "./auth.types";
+import type { PrimaryBadge } from "./auth.types";
interface CommentUser {
- id: string;
- username: string;
- avatar?: string;
+ id: string;
+ username: string;
+ avatar?: string;
primaryBadge?: PrimaryBadge;
- inDiscord?: boolean;
- isVip?: boolean;
- isMod?: boolean;
- isStaff?: boolean;
+ inDiscord?: boolean;
+ isVip?: boolean;
+ isMod?: boolean;
+ isStaff?: boolean;
}
interface Comment {
- id: string;
- content: string;
- rawContent?: string;
- userId: string;
- user: CommentUser;
- gameId?: string;
- bookId?: string;
- musicId?: string;
- artId?: string;
- showId?: string;
- mangaId?: string;
- hasPendingReports?: boolean;
- createdAt: Date;
- updatedAt: Date;
+ id: string;
+ content: string;
+ rawContent?: string;
+ userId: string;
+ user: CommentUser;
+ gameId?: string;
+ bookId?: string;
+ musicId?: string;
+ artId?: string;
+ showId?: string;
+ mangaId?: string;
+ hasPendingReports?: boolean;
+ createdAt: Date;
+ updatedAt: Date;
}
interface CreateCommentDto {
diff --git a/shared-types/src/lib/leaderboard.types.ts b/shared-types/src/lib/leaderboard.types.ts
index 3140d46..f5a3ba8 100644
--- a/shared-types/src/lib/leaderboard.types.ts
+++ b/shared-types/src/lib/leaderboard.types.ts
@@ -5,21 +5,21 @@
*/
interface LeaderboardUser {
- id: string;
- username: string;
- slug: string | null;
- avatar: string | null;
+ id: string;
+ username: string;
+ slug: string | null;
+ avatar: string | null;
primaryBadge: string | null;
- isVip: boolean;
- isMod: boolean;
- isStaff: boolean;
- createdAt: Date;
+ isVip: boolean;
+ isMod: boolean;
+ isStaff: boolean;
+ createdAt: Date;
}
interface SuggestionsLeaderboard extends LeaderboardUser {
- totalSuggestions: number;
+ totalSuggestions: number;
acceptedSuggestions: number;
- acceptanceRate: number;
+ acceptanceRate: number;
}
interface LikesLeaderboard extends LeaderboardUser {
@@ -31,20 +31,20 @@ interface CommentsLeaderboard extends LeaderboardUser {
}
interface OverallLeaderboard extends LeaderboardUser {
- totalSuggestions: number;
- totalLikes: number;
- totalComments: number;
- achievementCount: number;
+ totalSuggestions: number;
+ totalLikes: number;
+ totalComments: number;
+ achievementCount: number;
achievementPoints: number;
- currentStreak: number;
- diversityScore: number;
+ currentStreak: number;
+ diversityScore: number;
}
interface LeaderboardResponse {
- topSuggestions: SuggestionsLeaderboard[];
- topLikes: LikesLeaderboard[];
- topComments: CommentsLeaderboard[];
- topOverall: OverallLeaderboard[];
+ topSuggestions: Array;
+ topLikes: Array;
+ topComments: Array;
+ topOverall: Array;
}
export {
diff --git a/shared-types/src/lib/report.types.ts b/shared-types/src/lib/report.types.ts
index dca7a50..b25e449 100644
--- a/shared-types/src/lib/report.types.ts
+++ b/shared-types/src/lib/report.types.ts
@@ -74,10 +74,10 @@ export interface CommentReport {
export interface CommentReportWithDetails extends CommentReport {
reportedComment: {
- id: string;
- content: string;
+ id: string;
+ content: string;
rawContent?: string;
- userId: string;
+ userId: string;
user: {
id: string;
username: string;