generated from nhcarrigan/template
fix: resolve CSP and accessibility issues
- Allow inline styles in CSP for Angular component encapsulation - Hide skip-to-main-content link using screen-reader-only pattern - Add JavaScript handler for skip link to work across all routes - Add eslint-disable comments for intentional design choices
This commit is contained in:
@@ -13,9 +13,8 @@ const helmetPlugin: FastifyPluginAsync = async (app) => {
|
|||||||
contentSecurityPolicy: {
|
contentSecurityPolicy: {
|
||||||
directives: {
|
directives: {
|
||||||
defaultSrc: ["'self'"],
|
defaultSrc: ["'self'"],
|
||||||
// Remove unsafe-inline for better security
|
// Angular uses inline styles for component encapsulation, so we need to allow them
|
||||||
// Angular uses inline styles in development, but production builds should use external CSS
|
styleSrc: ["'self'", "'unsafe-inline'"],
|
||||||
styleSrc: ["'self'", process.env.NODE_ENV === "production" ? "'self'" : "'unsafe-inline'"],
|
|
||||||
imgSrc: ["'self'", "data:", "https:"],
|
imgSrc: ["'self'", "data:", "https:"],
|
||||||
scriptSrc: ["'self'"],
|
scriptSrc: ["'self'"],
|
||||||
connectSrc: ["'self'", process.env.FRONTEND_URL ?? "http://localhost:4200"],
|
connectSrc: ["'self'", process.env.FRONTEND_URL ?? "http://localhost:4200"],
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @copyright 2026 NHCarrigan
|
|
||||||
* @copyright 2026 NHCarrigan
|
* @copyright 2026 NHCarrigan
|
||||||
* @license Naomi's Public License
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getGreeting } from "../support/app.po";
|
import { getGreeting } from "../support/app.po";
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* @copyright 2026 NHCarrigan
|
|
||||||
* @copyright 2026 NHCarrigan
|
* @copyright 2026 NHCarrigan
|
||||||
* @license Naomi's Public License
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Gets the greeting element from the page.
|
||||||
|
* @returns A Cypress chainable to the h1 element.
|
||||||
*/
|
*/
|
||||||
export const getGreeting = (): Cypress.Chainable => {
|
export const getGreeting = (): Cypress.Chainable => {
|
||||||
return cy.get("h1");
|
return cy.get("h1");
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @copyright 2026 NHCarrigan
|
|
||||||
* @copyright 2026 NHCarrigan
|
* @copyright 2026 NHCarrigan
|
||||||
* @license Naomi's Public License
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// <reference types="cypress" />
|
/// <reference types="cypress" />
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* @license Naomi's Public License
|
* @license Naomi's Public License
|
||||||
* @author Naomi Carrigan
|
* @author Naomi Carrigan
|
||||||
*/
|
*/
|
||||||
|
/* eslint-disable unicorn/prevent-abbreviations -- e2e is a standard Cypress filename */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This example support/e2e.ts is processed and
|
* This example support/e2e.ts is processed and
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<a href="#main-content" class="skip-link">Skip to main content</a>
|
<a href="#main-content" class="skip-link" (click)="skipToMainContent($event)">Skip to main content</a>
|
||||||
<app-header></app-header>
|
<app-header></app-header>
|
||||||
<main id="main-content" class="main-content" tabindex="-1">
|
<main id="main-content" class="main-content" tabindex="-1">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
|
|||||||
@@ -1,3 +1,35 @@
|
|||||||
|
// Skip to main content link - visually hidden but accessible to screen readers
|
||||||
|
.skip-link {
|
||||||
|
position: absolute !important;
|
||||||
|
width: 1px !important;
|
||||||
|
height: 1px !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: -1px !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
clip: rect(0, 0, 0, 0) !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-link:focus {
|
||||||
|
position: fixed !important;
|
||||||
|
top: 0 !important;
|
||||||
|
left: 0 !important;
|
||||||
|
width: auto !important;
|
||||||
|
height: auto !important;
|
||||||
|
padding: 0.75rem 1.5rem !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
clip: auto !important;
|
||||||
|
white-space: normal !important;
|
||||||
|
background: var(--witch-rose) !important;
|
||||||
|
color: var(--witch-moon) !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
font-weight: 600 !important;
|
||||||
|
border-radius: 0 0 4px 0 !important;
|
||||||
|
z-index: 10000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
min-height: calc(100vh - 60px); // Assuming header is ~60px
|
min-height: calc(100vh - 60px); // Assuming header is ~60px
|
||||||
background-color: transparent; // Let the body background show through
|
background-color: transparent; // Let the body background show through
|
||||||
|
|||||||
@@ -18,4 +18,13 @@ export class App implements OnInit {
|
|||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.analytics.initialise();
|
this.analytics.initialise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skipToMainContent(event: Event): void {
|
||||||
|
event.preventDefault();
|
||||||
|
const mainContent = document.getElementById('main-content');
|
||||||
|
if (mainContent) {
|
||||||
|
mainContent.focus();
|
||||||
|
mainContent.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,23 +143,36 @@ button {
|
|||||||
background: var(--witch-plum);
|
background: var(--witch-plum);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip to main content link
|
// Skip to main content link - visually hidden but accessible to screen readers
|
||||||
.skip-link {
|
.skip-link {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -40px;
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-link:focus {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
margin: 0;
|
||||||
|
overflow: visible;
|
||||||
|
clip: auto;
|
||||||
|
white-space: normal;
|
||||||
background: var(--witch-rose);
|
background: var(--witch-rose);
|
||||||
color: var(--witch-moon);
|
color: var(--witch-moon);
|
||||||
padding: 0.75rem 1.5rem;
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border-radius: 0 0 4px 0;
|
border-radius: 0 0 4px 0;
|
||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
transition: top 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skip-link:focus {
|
|
||||||
top: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enhanced focus styles for keyboard navigation
|
// Enhanced focus styles for keyboard navigation
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
* @license Naomi's Public License
|
* @license Naomi's Public License
|
||||||
* @author Naomi Carrigan
|
* @author Naomi Carrigan
|
||||||
*/
|
*/
|
||||||
|
/* eslint-disable @typescript-eslint/naming-convention -- Achievement keys use snake_case for database identifiers */
|
||||||
|
/* eslint-disable sort-keys -- Achievements organized by category, not alphabetically */
|
||||||
|
/* eslint-disable sort-keys-fix/sort-keys-fix -- Achievements organized by category, not alphabetically */
|
||||||
|
/* eslint-disable stylistic/key-spacing -- Aligned for readability */
|
||||||
|
/* eslint-disable import/group-exports -- Single export at end of file */
|
||||||
import {
|
import {
|
||||||
AchievementCategory,
|
AchievementCategory,
|
||||||
type AchievementDefinition,
|
type AchievementDefinition,
|
||||||
@@ -11,6 +16,61 @@ import {
|
|||||||
|
|
||||||
export const ACHIEVEMENTS: Record<string, AchievementDefinition> = {
|
export const ACHIEVEMENTS: Record<string, AchievementDefinition> = {
|
||||||
|
|
||||||
|
like_enthusiast: {
|
||||||
|
category: AchievementCategory.Like,
|
||||||
|
description: "Like 25 items in the library",
|
||||||
|
icon: "💕",
|
||||||
|
key: "like_enthusiast",
|
||||||
|
points: 50,
|
||||||
|
title: "Enthusiast",
|
||||||
|
requirements: { count: 25 },
|
||||||
|
tier: AchievementTier.Bronze,
|
||||||
|
},
|
||||||
|
|
||||||
|
like_fan: {
|
||||||
|
category: AchievementCategory.Like,
|
||||||
|
description: "Like 100 items in the library",
|
||||||
|
icon: "💖",
|
||||||
|
key: "like_fan",
|
||||||
|
points: 100,
|
||||||
|
title: "Fan",
|
||||||
|
requirements: { count: 100 },
|
||||||
|
tier: AchievementTier.Silver,
|
||||||
|
},
|
||||||
|
|
||||||
|
suggestion_acceptance_100: {
|
||||||
|
category: AchievementCategory.Suggestion,
|
||||||
|
description: "Achieve 100% acceptance rate (minimum 10 suggestions)",
|
||||||
|
icon: "✨",
|
||||||
|
key: "suggestion_acceptance_100",
|
||||||
|
points: 500,
|
||||||
|
requirements: { count: 10, rate: 1 },
|
||||||
|
tier: AchievementTier.Platinum,
|
||||||
|
title: "Perfect Record",
|
||||||
|
},
|
||||||
|
|
||||||
|
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_acceptance_75: {
|
||||||
|
category: AchievementCategory.Suggestion,
|
||||||
|
description: "Maintain a 75%+ acceptance rate (minimum 20 suggestions)",
|
||||||
|
icon: "🎯",
|
||||||
|
key: "suggestion_acceptance_75",
|
||||||
|
points: 300,
|
||||||
|
requirements: { count: 20, rate: 0.75 },
|
||||||
|
title: "Quality Over Quantity",
|
||||||
|
tier: AchievementTier.Gold,
|
||||||
|
},
|
||||||
|
|
||||||
suggestion_approved: {
|
suggestion_approved: {
|
||||||
category: AchievementCategory.Suggestion,
|
category: AchievementCategory.Suggestion,
|
||||||
description: "Have your first suggestion accepted",
|
description: "Have your first suggestion accepted",
|
||||||
@@ -18,8 +78,19 @@ export const ACHIEVEMENTS: Record<string, AchievementDefinition> = {
|
|||||||
key: "suggestion_approved",
|
key: "suggestion_approved",
|
||||||
points: 50,
|
points: 50,
|
||||||
requirements: { count: 1 },
|
requirements: { count: 1 },
|
||||||
title: "Approved!",
|
|
||||||
tier: AchievementTier.Bronze,
|
tier: AchievementTier.Bronze,
|
||||||
|
title: "Approved!",
|
||||||
|
},
|
||||||
|
|
||||||
|
like_cinephile: {
|
||||||
|
description: "Like 50 shows/films",
|
||||||
|
category: AchievementCategory.Like,
|
||||||
|
key: "like_cinephile",
|
||||||
|
icon: "🎬",
|
||||||
|
title: "Cinephile",
|
||||||
|
points: 100,
|
||||||
|
requirements: { count: 50 },
|
||||||
|
tier: AchievementTier.Silver,
|
||||||
},
|
},
|
||||||
|
|
||||||
suggestion_contributor: {
|
suggestion_contributor: {
|
||||||
@@ -33,6 +104,17 @@ export const ACHIEVEMENTS: Record<string, AchievementDefinition> = {
|
|||||||
title: "Contributor",
|
title: "Contributor",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
like_diverse: {
|
||||||
|
description: "Like items from all 6 media types",
|
||||||
|
category: AchievementCategory.Like,
|
||||||
|
key: "like_diverse",
|
||||||
|
icon: "🌍",
|
||||||
|
title: "Diverse Taste",
|
||||||
|
points: 200,
|
||||||
|
requirements: { diversity: true },
|
||||||
|
tier: AchievementTier.Gold,
|
||||||
|
},
|
||||||
|
|
||||||
suggestion_dedicated: {
|
suggestion_dedicated: {
|
||||||
category: AchievementCategory.Suggestion,
|
category: AchievementCategory.Suggestion,
|
||||||
description: "Submit 100 suggestions to the library",
|
description: "Submit 100 suggestions to the library",
|
||||||
@@ -44,18 +126,42 @@ export const ACHIEVEMENTS: Record<string, AchievementDefinition> = {
|
|||||||
title: "Dedicated",
|
title: "Dedicated",
|
||||||
},
|
},
|
||||||
|
|
||||||
suggestion_acceptance_100: {
|
// ========== COMMENT ACHIEVEMENTS (12) ==========
|
||||||
key: "suggestion_acceptance_100",
|
comment_first: {
|
||||||
description: "Achieve 100% acceptance rate (minimum 10 suggestions)",
|
description: "Leave your first comment in the library",
|
||||||
title: "Perfect Record",
|
category: AchievementCategory.Comment,
|
||||||
category: AchievementCategory.Suggestion,
|
key: "comment_first",
|
||||||
icon: "✨",
|
icon: "💬",
|
||||||
tier: AchievementTier.Platinum,
|
title: "First Thoughts",
|
||||||
points: 500,
|
points: 25,
|
||||||
requirements: { count: 10, rate: 1.0 },
|
requirements: { count: 1 },
|
||||||
|
tier: AchievementTier.Bronze,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
suggestion_enthusiast: {
|
||||||
|
category: AchievementCategory.Suggestion,
|
||||||
|
description: "Submit 5 suggestions in one day",
|
||||||
|
icon: "🔥",
|
||||||
|
key: "suggestion_enthusiast",
|
||||||
|
points: 150,
|
||||||
|
requirements: { count: 5, dayRange: 1 },
|
||||||
|
title: "Suggestion Enthusiast",
|
||||||
|
tier: AchievementTier.Silver,
|
||||||
|
},
|
||||||
|
|
||||||
|
comment_critic: {
|
||||||
|
description: "Leave 50 comments in the library",
|
||||||
|
category: AchievementCategory.Comment,
|
||||||
|
key: "comment_critic",
|
||||||
|
icon: "🗣️",
|
||||||
|
title: "Critic",
|
||||||
|
points: 100,
|
||||||
|
requirements: { count: 50 },
|
||||||
|
tier: AchievementTier.Silver,
|
||||||
|
},
|
||||||
|
|
||||||
// ========== SUGGESTION ACHIEVEMENTS (15) ==========
|
// ========== SUGGESTION ACHIEVEMENTS (15) ==========
|
||||||
suggestion_first_steps: {
|
suggestion_first_steps: {
|
||||||
category: AchievementCategory.Suggestion,
|
category: AchievementCategory.Suggestion,
|
||||||
description: "Submit your first 10 suggestions to the library",
|
description: "Submit your first 10 suggestions to the library",
|
||||||
icon: "🌱",
|
icon: "🌱",
|
||||||
@@ -65,16 +171,18 @@ suggestion_first_steps: {
|
|||||||
tier: AchievementTier.Bronze,
|
tier: AchievementTier.Bronze,
|
||||||
title: "First Steps",
|
title: "First Steps",
|
||||||
},
|
},
|
||||||
suggestion_acceptance_75: {
|
|
||||||
description: "Maintain a 75%+ acceptance rate (minimum 20 suggestions)",
|
comment_expert: {
|
||||||
key: "suggestion_acceptance_75",
|
category: AchievementCategory.Comment,
|
||||||
category: AchievementCategory.Suggestion,
|
description: "Leave 100 comments in the library",
|
||||||
title: "Quality Over Quantity",
|
icon: "🎭",
|
||||||
icon: "🎯",
|
key: "comment_expert",
|
||||||
points: 300,
|
points: 250,
|
||||||
|
title: "Expert Critic",
|
||||||
|
requirements: { count: 100 },
|
||||||
tier: AchievementTier.Gold,
|
tier: AchievementTier.Gold,
|
||||||
requirements: { count: 20, rate: 0.75 },
|
|
||||||
},
|
},
|
||||||
|
|
||||||
suggestion_legend: {
|
suggestion_legend: {
|
||||||
category: AchievementCategory.Suggestion,
|
category: AchievementCategory.Suggestion,
|
||||||
description: "Submit 500 suggestions to the library",
|
description: "Submit 500 suggestions to the library",
|
||||||
@@ -85,16 +193,18 @@ suggestion_first_steps: {
|
|||||||
tier: AchievementTier.Diamond,
|
tier: AchievementTier.Diamond,
|
||||||
title: "Legend",
|
title: "Legend",
|
||||||
},
|
},
|
||||||
like_enthusiast: {
|
|
||||||
key: "like_enthusiast",
|
comment_legend: {
|
||||||
description: "Like 25 items in the library",
|
category: AchievementCategory.Comment,
|
||||||
title: "Enthusiast",
|
description: "Leave 500 comments in the library",
|
||||||
category: AchievementCategory.Like,
|
icon: "🏅",
|
||||||
icon: "💕",
|
key: "comment_legend",
|
||||||
tier: AchievementTier.Bronze,
|
points: 1000,
|
||||||
points: 50,
|
title: "Review Legend",
|
||||||
requirements: { count: 25 },
|
requirements: { count: 500 },
|
||||||
|
tier: AchievementTier.Diamond,
|
||||||
},
|
},
|
||||||
|
|
||||||
suggestion_master: {
|
suggestion_master: {
|
||||||
category: AchievementCategory.Suggestion,
|
category: AchievementCategory.Suggestion,
|
||||||
description: "Submit 250 suggestions to the library",
|
description: "Submit 250 suggestions to the library",
|
||||||
@@ -102,19 +212,21 @@ suggestion_first_steps: {
|
|||||||
key: "suggestion_master",
|
key: "suggestion_master",
|
||||||
points: 500,
|
points: 500,
|
||||||
requirements: { count: 250 },
|
requirements: { count: 250 },
|
||||||
title: "Master Curator",
|
|
||||||
tier: AchievementTier.Platinum,
|
tier: AchievementTier.Platinum,
|
||||||
|
title: "Master Curator",
|
||||||
},
|
},
|
||||||
like_fan: {
|
|
||||||
description: "Like 100 items in the library",
|
comment_detailed: {
|
||||||
key: "like_fan",
|
category: AchievementCategory.Comment,
|
||||||
category: AchievementCategory.Like,
|
description: "Write 10 comments with 500+ characters",
|
||||||
title: "Fan",
|
icon: "📝",
|
||||||
icon: "💖",
|
key: "comment_detailed",
|
||||||
points: 100,
|
points: 150,
|
||||||
|
requirements: { count: 10 },
|
||||||
|
title: "Detailed Critic",
|
||||||
tier: AchievementTier.Silver,
|
tier: AchievementTier.Silver,
|
||||||
requirements: { count: 100 },
|
|
||||||
},
|
},
|
||||||
|
|
||||||
suggestion_quality_10: {
|
suggestion_quality_10: {
|
||||||
category: AchievementCategory.Suggestion,
|
category: AchievementCategory.Suggestion,
|
||||||
description: "Have 10 suggestions accepted",
|
description: "Have 10 suggestions accepted",
|
||||||
@@ -122,59 +234,74 @@ suggestion_first_steps: {
|
|||||||
key: "suggestion_quality_10",
|
key: "suggestion_quality_10",
|
||||||
points: 200,
|
points: 200,
|
||||||
requirements: { count: 10 },
|
requirements: { count: 10 },
|
||||||
title: "Elite Curator",
|
|
||||||
tier: AchievementTier.Gold,
|
tier: AchievementTier.Gold,
|
||||||
},
|
title: "Elite Curator",
|
||||||
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: {
|
comment_essay: {
|
||||||
description: "Like 50 shows/films",
|
category: AchievementCategory.Comment,
|
||||||
key: "like_cinephile",
|
description: "Write 5 comments with 1000+ characters",
|
||||||
category: AchievementCategory.Like,
|
icon: "📄",
|
||||||
title: "Cinephile",
|
key: "comment_essay",
|
||||||
icon: "🎬",
|
points: 300,
|
||||||
points: 100,
|
requirements: { count: 5 },
|
||||||
|
tier: AchievementTier.Gold,
|
||||||
|
title: "Essay Writer",
|
||||||
|
},
|
||||||
|
|
||||||
|
suggestion_quality_100: {
|
||||||
|
description: "Have 100 suggestions accepted",
|
||||||
|
category: AchievementCategory.Suggestion,
|
||||||
|
key: "suggestion_quality_100",
|
||||||
|
icon: "👸",
|
||||||
|
title: "Ultimate Curator",
|
||||||
|
points: 1500,
|
||||||
|
requirements: { count: 100 },
|
||||||
|
tier: AchievementTier.Diamond,
|
||||||
|
},
|
||||||
|
|
||||||
|
comment_diverse: {
|
||||||
|
category: AchievementCategory.Comment,
|
||||||
|
description: "Comment on all 6 media types",
|
||||||
|
icon: "🎨",
|
||||||
|
key: "comment_diverse",
|
||||||
|
points: 250,
|
||||||
|
requirements: { diversity: true },
|
||||||
|
title: "Well-Rounded Critic",
|
||||||
|
tier: AchievementTier.Gold,
|
||||||
|
},
|
||||||
|
|
||||||
|
suggestion_quality_25: {
|
||||||
|
description: "Have 25 suggestions accepted",
|
||||||
|
category: AchievementCategory.Suggestion,
|
||||||
|
key: "suggestion_quality_25",
|
||||||
|
icon: "💫",
|
||||||
|
title: "Master Curator",
|
||||||
|
points: 400,
|
||||||
|
requirements: { count: 25 },
|
||||||
|
tier: AchievementTier.Platinum,
|
||||||
|
},
|
||||||
|
|
||||||
|
comment_first_to_comment: {
|
||||||
|
category: AchievementCategory.Comment,
|
||||||
|
description: "Be the first to comment on 10 items",
|
||||||
|
icon: "🗨️",
|
||||||
|
key: "comment_first_to_comment",
|
||||||
|
points: 200,
|
||||||
|
requirements: { count: 10 },
|
||||||
tier: AchievementTier.Silver,
|
tier: AchievementTier.Silver,
|
||||||
requirements: { count: 50 },
|
title: "Discussion Starter",
|
||||||
|
},
|
||||||
|
|
||||||
|
comment_master: {
|
||||||
|
category: AchievementCategory.Comment,
|
||||||
|
description: "Leave 250 comments in the library",
|
||||||
|
icon: "📖",
|
||||||
|
key: "comment_master",
|
||||||
|
points: 500,
|
||||||
|
title: "Master Reviewer",
|
||||||
|
requirements: { count: 250 },
|
||||||
|
tier: AchievementTier.Platinum,
|
||||||
},
|
},
|
||||||
|
|
||||||
suggestion_quality_5: {
|
suggestion_quality_5: {
|
||||||
@@ -188,201 +315,6 @@ suggestion_first_steps: {
|
|||||||
requirements: { count: 5 },
|
requirements: { count: 5 },
|
||||||
},
|
},
|
||||||
|
|
||||||
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,
|
|
||||||
requirements: { diversity: true },
|
|
||||||
},
|
|
||||||
|
|
||||||
// ========== 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: {
|
|
||||||
key: "suggestion_quality_50",
|
|
||||||
title: "Grand Master",
|
|
||||||
description: "Have 50 suggestions accepted",
|
|
||||||
category: AchievementCategory.Suggestion,
|
|
||||||
tier: AchievementTier.Platinum,
|
|
||||||
icon: "🎖️",
|
|
||||||
points: 700,
|
|
||||||
requirements: { count: 50 },
|
|
||||||
},
|
|
||||||
|
|
||||||
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: {
|
|
||||||
description: "Submit accepted suggestions across all 6 media types",
|
|
||||||
key: "suggestion_renaissance",
|
|
||||||
category: AchievementCategory.Suggestion,
|
|
||||||
title: "Renaissance Person",
|
|
||||||
icon: "🌈",
|
|
||||||
points: 400,
|
|
||||||
tier: AchievementTier.Gold,
|
|
||||||
requirements: { diversity: true },
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
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: {
|
|
||||||
description: "Like your first item in the library",
|
|
||||||
key: "like_first",
|
|
||||||
category: AchievementCategory.Like,
|
|
||||||
title: "First Like",
|
|
||||||
icon: "❤️",
|
|
||||||
points: 25,
|
|
||||||
tier: AchievementTier.Bronze,
|
|
||||||
requirements: { count: 1 },
|
|
||||||
},
|
|
||||||
|
|
||||||
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",
|
|
||||||
description: "Like 1000 items in the library",
|
|
||||||
title: "Legendary Fan",
|
|
||||||
category: AchievementCategory.Like,
|
|
||||||
icon: "💞",
|
|
||||||
tier: AchievementTier.Diamond,
|
|
||||||
points: 1000,
|
|
||||||
requirements: { count: 1000 },
|
|
||||||
},
|
|
||||||
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",
|
|
||||||
description: "Like 50 games",
|
|
||||||
title: "Gamer",
|
|
||||||
category: AchievementCategory.Like,
|
|
||||||
icon: "🎮",
|
|
||||||
tier: AchievementTier.Silver,
|
|
||||||
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",
|
|
||||||
description: "Like 50 music albums",
|
|
||||||
title: "Music Enthusiast",
|
|
||||||
category: AchievementCategory.Like,
|
|
||||||
icon: "🎵",
|
|
||||||
tier: AchievementTier.Silver,
|
|
||||||
points: 100,
|
|
||||||
requirements: { count: 50 },
|
|
||||||
},
|
|
||||||
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: {
|
comment_novel: {
|
||||||
category: AchievementCategory.Comment,
|
category: AchievementCategory.Comment,
|
||||||
description: "Write 3 comments with 2000+ characters",
|
description: "Write 3 comments with 2000+ characters",
|
||||||
@@ -393,26 +325,40 @@ like_first: {
|
|||||||
tier: AchievementTier.Platinum,
|
tier: AchievementTier.Platinum,
|
||||||
title: "Novel Writer",
|
title: "Novel Writer",
|
||||||
},
|
},
|
||||||
like_binge: {
|
|
||||||
key: "like_binge",
|
suggestion_quality_50: {
|
||||||
title: "Binge Liker",
|
key: "suggestion_quality_50",
|
||||||
description: "Like 20+ items in one day",
|
description: "Have 50 suggestions accepted",
|
||||||
category: AchievementCategory.Like,
|
title: "Grand Master",
|
||||||
tier: AchievementTier.Silver,
|
category: AchievementCategory.Suggestion,
|
||||||
icon: "⚡",
|
icon: "🎖️",
|
||||||
points: 150,
|
tier: AchievementTier.Platinum,
|
||||||
requirements: { count: 20, dayRange: 1 },
|
points: 700,
|
||||||
|
requirements: { count: 50 },
|
||||||
},
|
},
|
||||||
|
|
||||||
comment_reviewer: {
|
comment_reviewer: {
|
||||||
key: "comment_reviewer",
|
|
||||||
description: "Leave 10 comments in the library",
|
description: "Leave 10 comments in the library",
|
||||||
title: "Reviewer",
|
|
||||||
category: AchievementCategory.Comment,
|
category: AchievementCategory.Comment,
|
||||||
|
key: "comment_reviewer",
|
||||||
icon: "✍️",
|
icon: "✍️",
|
||||||
tier: AchievementTier.Bronze,
|
title: "Reviewer",
|
||||||
points: 50,
|
points: 50,
|
||||||
requirements: { count: 10 },
|
requirements: { count: 10 },
|
||||||
|
tier: AchievementTier.Bronze,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
suggestion_renaissance: {
|
||||||
|
description: "Submit accepted suggestions across all 6 media types",
|
||||||
|
category: AchievementCategory.Suggestion,
|
||||||
|
key: "suggestion_renaissance",
|
||||||
|
icon: "🌈",
|
||||||
|
title: "Renaissance Person",
|
||||||
|
points: 400,
|
||||||
|
requirements: { diversity: true },
|
||||||
|
tier: AchievementTier.Gold,
|
||||||
|
},
|
||||||
|
|
||||||
comment_thoughtful: {
|
comment_thoughtful: {
|
||||||
category: AchievementCategory.Comment,
|
category: AchievementCategory.Comment,
|
||||||
description: "Comment on 50 different items",
|
description: "Comment on 50 different items",
|
||||||
@@ -425,36 +371,86 @@ like_first: {
|
|||||||
},
|
},
|
||||||
|
|
||||||
engagement_early_adopter: {
|
engagement_early_adopter: {
|
||||||
description: "Be among the first 10 users to join",
|
|
||||||
category: AchievementCategory.Engagement,
|
category: AchievementCategory.Engagement,
|
||||||
key: "engagement_early_adopter",
|
description: "Be among the first 10 users to join",
|
||||||
icon: "🌟",
|
icon: "🌟",
|
||||||
title: "Early Adopter",
|
key: "engagement_early_adopter",
|
||||||
points: 1000,
|
points: 1000,
|
||||||
requirements: {},
|
requirements: {},
|
||||||
tier: AchievementTier.Diamond,
|
tier: AchievementTier.Diamond,
|
||||||
|
title: "Early Adopter",
|
||||||
},
|
},
|
||||||
|
// ========== LIKE ACHIEVEMENTS (12) ==========
|
||||||
engagement_power_user: {
|
like_first: {
|
||||||
description: "Achieve Triple Threat 10 times",
|
description: "Like your first item in the library",
|
||||||
category: AchievementCategory.Engagement,
|
key: "like_first",
|
||||||
key: "engagement_power_user",
|
category: AchievementCategory.Like,
|
||||||
icon: "💫",
|
title: "First Like",
|
||||||
title: "Power User",
|
icon: "❤️",
|
||||||
points: 750,
|
points: 25,
|
||||||
requirements: { count: 10 },
|
tier: AchievementTier.Bronze,
|
||||||
tier: AchievementTier.Platinum,
|
requirements: { count: 1 },
|
||||||
},
|
},
|
||||||
|
|
||||||
engagement_founding_100: {
|
engagement_founding_100: {
|
||||||
category: AchievementCategory.Engagement,
|
category: AchievementCategory.Engagement,
|
||||||
description: "Be among the first 100 users to join",
|
description: "Be among the first 100 users to join",
|
||||||
icon: "🎖️",
|
icon: "🎖️",
|
||||||
key: "engagement_founding_100",
|
key: "engagement_founding_100",
|
||||||
points: 500,
|
points: 500,
|
||||||
title: "Founding Member",
|
|
||||||
requirements: {},
|
requirements: {},
|
||||||
tier: AchievementTier.Gold,
|
tier: AchievementTier.Gold,
|
||||||
|
title: "Founding Member",
|
||||||
|
},
|
||||||
|
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 },
|
||||||
|
},
|
||||||
|
engagement_founding_1000: {
|
||||||
|
category: AchievementCategory.Engagement,
|
||||||
|
description: "Be among the first 1000 users to join",
|
||||||
|
icon: "🚀",
|
||||||
|
key: "engagement_founding_1000",
|
||||||
|
points: 200,
|
||||||
|
requirements: {},
|
||||||
|
tier: AchievementTier.Silver,
|
||||||
|
title: "Pioneer",
|
||||||
|
},
|
||||||
|
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 },
|
||||||
|
},
|
||||||
|
engagement_power_user: {
|
||||||
|
category: AchievementCategory.Engagement,
|
||||||
|
description: "Achieve Triple Threat 10 times",
|
||||||
|
icon: "💫",
|
||||||
|
key: "engagement_power_user",
|
||||||
|
points: 750,
|
||||||
|
requirements: { count: 10 },
|
||||||
|
tier: AchievementTier.Platinum,
|
||||||
|
title: "Power User",
|
||||||
|
},
|
||||||
|
|
||||||
|
like_legendary: {
|
||||||
|
key: "like_legendary",
|
||||||
|
description: "Like 1000 items in the library",
|
||||||
|
title: "Legendary Fan",
|
||||||
|
category: AchievementCategory.Like,
|
||||||
|
icon: "💞",
|
||||||
|
tier: AchievementTier.Diamond,
|
||||||
|
points: 1000,
|
||||||
|
requirements: { count: 1000 },
|
||||||
},
|
},
|
||||||
|
|
||||||
engagement_streak_100: {
|
engagement_streak_100: {
|
||||||
@@ -463,31 +459,42 @@ like_first: {
|
|||||||
icon: "🏆",
|
icon: "🏆",
|
||||||
key: "engagement_streak_100",
|
key: "engagement_streak_100",
|
||||||
points: 500,
|
points: 500,
|
||||||
title: "Committed",
|
|
||||||
requirements: { streak: 100 },
|
requirements: { streak: 100 },
|
||||||
tier: AchievementTier.Gold,
|
tier: AchievementTier.Gold,
|
||||||
|
title: "Committed",
|
||||||
},
|
},
|
||||||
|
|
||||||
engagement_founding_1000: {
|
like_gamer: {
|
||||||
category: AchievementCategory.Engagement,
|
key: "like_gamer",
|
||||||
description: "Be among the first 1000 users to join",
|
description: "Like 50 games",
|
||||||
icon: "🚀",
|
title: "Gamer",
|
||||||
key: "engagement_founding_1000",
|
category: AchievementCategory.Like,
|
||||||
points: 200,
|
icon: "🎮",
|
||||||
requirements: {},
|
|
||||||
title: "Pioneer",
|
|
||||||
tier: AchievementTier.Silver,
|
tier: AchievementTier.Silver,
|
||||||
|
points: 100,
|
||||||
|
requirements: { count: 50 },
|
||||||
},
|
},
|
||||||
|
|
||||||
engagement_streak_30: {
|
engagement_streak_30: {
|
||||||
description: "Login for 30 days in a row",
|
|
||||||
category: AchievementCategory.Engagement,
|
category: AchievementCategory.Engagement,
|
||||||
key: "engagement_streak_30",
|
description: "Login for 30 days in a row",
|
||||||
icon: "💪",
|
icon: "💪",
|
||||||
title: "Dedicated",
|
key: "engagement_streak_30",
|
||||||
points: 250,
|
points: 250,
|
||||||
requirements: { streak: 30 },
|
requirements: { streak: 30 },
|
||||||
tier: AchievementTier.Silver,
|
tier: AchievementTier.Silver,
|
||||||
|
title: "Dedicated",
|
||||||
|
},
|
||||||
|
|
||||||
|
like_music: {
|
||||||
|
key: "like_music",
|
||||||
|
description: "Like 50 music albums",
|
||||||
|
title: "Music Enthusiast",
|
||||||
|
category: AchievementCategory.Like,
|
||||||
|
icon: "🎵",
|
||||||
|
tier: AchievementTier.Silver,
|
||||||
|
points: 100,
|
||||||
|
requirements: { count: 50 },
|
||||||
},
|
},
|
||||||
|
|
||||||
engagement_streak_365: {
|
engagement_streak_365: {
|
||||||
@@ -496,20 +503,31 @@ like_first: {
|
|||||||
icon: "⚡",
|
icon: "⚡",
|
||||||
key: "engagement_streak_365",
|
key: "engagement_streak_365",
|
||||||
points: 2000,
|
points: 2000,
|
||||||
title: "Unstoppable",
|
|
||||||
requirements: { streak: 365 },
|
requirements: { streak: 365 },
|
||||||
tier: AchievementTier.Diamond,
|
tier: AchievementTier.Diamond,
|
||||||
|
title: "Unstoppable",
|
||||||
},
|
},
|
||||||
|
|
||||||
engagement_streak_7: {
|
engagement_streak_7: {
|
||||||
description: "Login for 7 days in a row",
|
|
||||||
key: "engagement_streak_7",
|
|
||||||
category: AchievementCategory.Engagement,
|
category: AchievementCategory.Engagement,
|
||||||
title: "Daily Visitor",
|
description: "Login for 7 days in a row",
|
||||||
icon: "🔥",
|
icon: "🔥",
|
||||||
|
key: "engagement_streak_7",
|
||||||
points: 100,
|
points: 100,
|
||||||
tier: AchievementTier.Bronze,
|
|
||||||
requirements: { streak: 7 },
|
requirements: { streak: 7 },
|
||||||
|
tier: AchievementTier.Bronze,
|
||||||
|
title: "Daily Visitor",
|
||||||
|
},
|
||||||
|
|
||||||
|
like_binge: {
|
||||||
|
key: "like_binge",
|
||||||
|
title: "Binge Liker",
|
||||||
|
description: "Like 20+ items in one day",
|
||||||
|
category: AchievementCategory.Like,
|
||||||
|
tier: AchievementTier.Silver,
|
||||||
|
icon: "⚡",
|
||||||
|
points: 150,
|
||||||
|
requirements: { count: 20, dayRange: 1 },
|
||||||
},
|
},
|
||||||
|
|
||||||
engagement_triple_threat: {
|
engagement_triple_threat: {
|
||||||
@@ -519,11 +537,11 @@ like_first: {
|
|||||||
key: "engagement_triple_threat",
|
key: "engagement_triple_threat",
|
||||||
points: 200,
|
points: 200,
|
||||||
requirements: { dayRange: 1 },
|
requirements: { dayRange: 1 },
|
||||||
title: "Triple Threat",
|
|
||||||
tier: AchievementTier.Silver,
|
tier: AchievementTier.Silver,
|
||||||
|
title: "Triple Threat",
|
||||||
},
|
},
|
||||||
|
|
||||||
engagement_veteran_180: {
|
engagement_veteran_180: {
|
||||||
category: AchievementCategory.Engagement,
|
category: AchievementCategory.Engagement,
|
||||||
description: "Have an account for 6 months",
|
description: "Have an account for 6 months",
|
||||||
icon: "📅",
|
icon: "📅",
|
||||||
@@ -533,17 +551,7 @@ engagement_veteran_180: {
|
|||||||
tier: AchievementTier.Silver,
|
tier: AchievementTier.Silver,
|
||||||
title: "Seasoned",
|
title: "Seasoned",
|
||||||
},
|
},
|
||||||
// ========== ENGAGEMENT ACHIEVEMENTS (15) ==========
|
|
||||||
engagement_welcome: {
|
|
||||||
key: "engagement_welcome",
|
|
||||||
title: "Welcome!",
|
|
||||||
description: "Complete your profile setup",
|
|
||||||
category: AchievementCategory.Engagement,
|
|
||||||
tier: AchievementTier.Bronze,
|
|
||||||
icon: "👋",
|
|
||||||
points: 25,
|
|
||||||
requirements: {},
|
|
||||||
},
|
|
||||||
engagement_veteran_1825: {
|
engagement_veteran_1825: {
|
||||||
category: AchievementCategory.Engagement,
|
category: AchievementCategory.Engagement,
|
||||||
description: "Have an account for 5 years",
|
description: "Have an account for 5 years",
|
||||||
@@ -554,6 +562,7 @@ engagement_welcome: {
|
|||||||
tier: AchievementTier.Diamond,
|
tier: AchievementTier.Diamond,
|
||||||
title: "Legend",
|
title: "Legend",
|
||||||
},
|
},
|
||||||
|
|
||||||
engagement_veteran_30: {
|
engagement_veteran_30: {
|
||||||
category: AchievementCategory.Engagement,
|
category: AchievementCategory.Engagement,
|
||||||
description: "Have an account for 30 days",
|
description: "Have an account for 30 days",
|
||||||
@@ -564,6 +573,7 @@ engagement_welcome: {
|
|||||||
tier: AchievementTier.Bronze,
|
tier: AchievementTier.Bronze,
|
||||||
title: "Veteran",
|
title: "Veteran",
|
||||||
},
|
},
|
||||||
|
|
||||||
engagement_veteran_365: {
|
engagement_veteran_365: {
|
||||||
category: AchievementCategory.Engagement,
|
category: AchievementCategory.Engagement,
|
||||||
description: "Have an account for 1 year",
|
description: "Have an account for 1 year",
|
||||||
@@ -574,6 +584,7 @@ engagement_welcome: {
|
|||||||
tier: AchievementTier.Gold,
|
tier: AchievementTier.Gold,
|
||||||
title: "Longstanding",
|
title: "Longstanding",
|
||||||
},
|
},
|
||||||
|
|
||||||
engagement_veteran_730: {
|
engagement_veteran_730: {
|
||||||
category: AchievementCategory.Engagement,
|
category: AchievementCategory.Engagement,
|
||||||
description: "Have an account for 2 years",
|
description: "Have an account for 2 years",
|
||||||
@@ -584,6 +595,17 @@ engagement_welcome: {
|
|||||||
tier: AchievementTier.Platinum,
|
tier: AchievementTier.Platinum,
|
||||||
title: "Elder",
|
title: "Elder",
|
||||||
},
|
},
|
||||||
|
// ========== ENGAGEMENT ACHIEVEMENTS (15) ==========
|
||||||
|
engagement_welcome: {
|
||||||
|
category: AchievementCategory.Engagement,
|
||||||
|
description: "Complete your profile setup",
|
||||||
|
icon: "👋",
|
||||||
|
key: "engagement_welcome",
|
||||||
|
points: 25,
|
||||||
|
requirements: {},
|
||||||
|
tier: AchievementTier.Bronze,
|
||||||
|
title: "Welcome!",
|
||||||
|
},
|
||||||
|
|
||||||
report_accuracy_80: {
|
report_accuracy_80: {
|
||||||
category: AchievementCategory.Report,
|
category: AchievementCategory.Report,
|
||||||
@@ -663,14 +685,14 @@ engagement_welcome: {
|
|||||||
},
|
},
|
||||||
// ========== REPORT ACHIEVEMENTS (8) ==========
|
// ========== REPORT ACHIEVEMENTS (8) ==========
|
||||||
report_watchful: {
|
report_watchful: {
|
||||||
description: "Submit your first valid report (ACTION_TAKEN)",
|
|
||||||
category: AchievementCategory.Report,
|
category: AchievementCategory.Report,
|
||||||
key: "report_watchful",
|
description: "Submit your first valid report (ACTION_TAKEN)",
|
||||||
icon: "👀",
|
icon: "👀",
|
||||||
title: "Watchful Eye",
|
key: "report_watchful",
|
||||||
points: 50,
|
points: 50,
|
||||||
requirements: { count: 1 },
|
requirements: { count: 1 },
|
||||||
tier: AchievementTier.Bronze,
|
tier: AchievementTier.Bronze,
|
||||||
|
title: "Watchful Eye",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
* @license Naomi's Public License
|
* @license Naomi's Public License
|
||||||
* @author Naomi Carrigan
|
* @author Naomi Carrigan
|
||||||
*/
|
*/
|
||||||
|
/* eslint-disable @typescript-eslint/naming-convention -- Enum members use PascalCase for display values */
|
||||||
|
/* eslint-disable import/group-exports -- Multiple exports for better organization */
|
||||||
|
|
||||||
export enum AchievementCategory {
|
export enum AchievementCategory {
|
||||||
Suggestion = "SUGGESTION",
|
Suggestion = "SUGGESTION",
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* @copyright NHCarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
/* eslint-disable @typescript-eslint/naming-convention -- Enum members use UPPER_CASE for database values */
|
||||||
|
/* eslint-disable import/group-exports -- Multiple exports for better organization */
|
||||||
|
|
||||||
export enum ReportReason {
|
export enum ReportReason {
|
||||||
INAPPROPRIATE_CONTENT = "INAPPROPRIATE_CONTENT",
|
INAPPROPRIATE_CONTENT = "INAPPROPRIATE_CONTENT",
|
||||||
HARASSMENT = "HARASSMENT",
|
HARASSMENT = "HARASSMENT",
|
||||||
|
|||||||
Reference in New Issue
Block a user