Skip to main content

What are Categories?

In Tareas, Categories (also called “Kingdoms” or “Realms”) are organizational groups that help users classify and theme their quests. Each category has unique visual styling with custom colors, icons, and glow effects.
Categories provide both functional organization and visual theming, making it easy to distinguish between different types of work at a glance.

Category Model Structure

Here’s the TypeScript interface from the codebase:
export interface Category {
  id: string;
  key: 'design' | 'dev' | 'marketing' | 'primary' | 'innovation' | 'strategy' | 'heal' | 'study' | 'funny';
  name: string;
  colorClass: string;
  icon: string;
}

Category Properties

Identification

  • id: Unique identifier (UUID generated with crypto.randomUUID())
  • key: Predefined category type constant
  • name: Display name shown in the UI

Visual Styling

  • colorClass: CSS class defining the category’s color theme
  • icon: Ionic icon name for visual representation

Available Category Types

Tareas includes 9 predefined category types:
const categories: Category[] = [
  { id: '1', key: 'design', name: 'Diseño', colorClass: 'realm-design', icon: 'brush' },
  { id: '2', key: 'dev', name: 'Desarrollo', colorClass: 'realm-dev', icon: 'terminal' },
  { id: '3', key: 'marketing', name: 'Marketing', colorClass: 'realm-marketing', icon: 'analytics' },
  { id: '4', key: 'primary', name: 'Principal', colorClass: 'realm-circle', icon: 'star' },
  { id: '5', key: 'innovation', name: 'Innovación', colorClass: 'realm-innovation', icon: 'rocket' },
  { id: '6', key: 'heal', name: 'Salud', colorClass: 'realm-heal', icon: 'heart' },
  { id: '7', key: 'study', name: 'Estudio', colorClass: 'realm-study', icon: 'school' },
  { id: '8', key: 'funny', name: 'Diversión', colorClass: 'realm-funny', icon: 'happy' }
];
  • Key: design
  • Icon: brush
  • Color Class: realm-design
  • Use Case: Creative work, UI/UX design, branding
  • Key: dev
  • Icon: terminal
  • Color Class: realm-dev
  • Use Case: Coding, software development, technical tasks
  • Key: marketing
  • Icon: analytics
  • Color Class: realm-marketing
  • Use Case: Marketing campaigns, content creation, analytics
  • Key: primary
  • Icon: star
  • Color Class: realm-circle
  • Use Case: High-priority tasks, flagship projects
  • Key: innovation
  • Icon: rocket
  • Color Class: realm-innovation
  • Use Case: Experimental projects, R&D, new ideas
  • Key: heal
  • Icon: heart
  • Color Class: realm-heal
  • Use Case: Wellness, fitness, self-care activities
  • Key: study
  • Icon: school
  • Color Class: realm-study
  • Use Case: Learning, courses, educational content
  • Key: funny
  • Icon: happy
  • Color Class: realm-funny
  • Use Case: Entertainment, hobbies, leisure activities

Category Color Theming

Each category has unique color mappings for visual distinction:
getRealmColor(colorClass: string): string {
  switch(colorClass) {
    case 'realm-design': return '#3b82f6';  // Blue
    case 'realm-dev': return '#a855f7';      // Purple
    case 'realm-marketing': return '#f97316'; // Orange
    case 'realm-circle': return '#10b981';   // Green
    case 'realm-innovation': return '#ec4899'; // Pink
    case 'realm-heal': return '#ef4444';     // Red
    case 'realm-study': return '#8b5cf6';    // Violet
    case 'realm-funny': return '#f59e0b';    // Amber
    default: return '#10b981';               // Default green
  }
}
The realm-* prefix in colorClass indicates these are themed “kingdoms” or “realms” in the gamification system.

Category Service

The CategoryService manages CRUD operations with localStorage persistence:
@Injectable({
  providedIn: 'root'
})
export class CategoryService {
  private storageKey = 'categories';
  
  // Observable for reactive updates
  private categoriesSubject = new BehaviorSubject<Category[]>(this.loadFromStorage());
  categories$ = this.categoriesSubject.asObservable();

  // Get all categories
  getAll(): Category[] {
    return this.categoriesSubject.value;
  }

  // Get category by id
  getById(id: string): Category | undefined {
    return this.getAll().find(cat => cat.id === id);
  }

  // Create new category
  create(category: Omit<Category, 'id'>): Category {
    const newCategory: Category = {
      ...category,
      id: crypto.randomUUID()
    };
    const categories = [...this.getAll(), newCategory];
    this.saveToStorage(categories);
    return newCategory;
  }

  // Update category
  update(id: string, updatedCategory: Partial<Category>): Category | null {
    const categories = this.getAll().map(cat =>
      cat.id === id ? { ...cat, ...updatedCategory } : cat
    );
    this.saveToStorage(categories);
    return categories.find(cat => cat.id === id) || null;
  }

  // Delete category
  delete(id: string): boolean {
    const categories = this.getAll().filter(cat => cat.id !== id);
    const deleted = categories.length < this.getAll().length;
    this.saveToStorage(categories);
    return deleted;
  }
}

Creating a Category

Example of creating a new category:
const newCategory = categoryService.create({
  key: 'dev',
  name: 'Desarrollo',
  colorClass: 'realm-dev',
  icon: 'terminal'
});

// Returns:
// {
//   id: 'generated-uuid-here',
//   key: 'dev',
//   name: 'Desarrollo',
//   colorClass: 'realm-dev',
//   icon: 'terminal'
// }

Quest-Category Relationship

Categories are linked to Quests through the category and kingdom fields:
interface Quest {
  category: string;     // Category name or key
  kingdom: string;      // Associated realm/kingdom
  colorClass: string;   // Inherits from category
  glowClass: string;    // Visual effect from category
  // ... other properties
}
When a quest is assigned to a category, it automatically inherits that category’s visual properties (colorClass, glowClass, icon).

Category Filtering

Filter quests by category in the UI:
// From quest.service.ts
getQuestsByCategory(category: string): Quest[] {
  return this.quest$.value.filter(quest => quest.category === category);
}

Persistence

Categories are stored in localStorage:
private saveToStorage(categories: Category[]) {
  localStorage.setItem(this.storageKey, JSON.stringify(categories));
  this.categoriesSubject.next(categories); // Emit changes to subscribers
}

private loadFromStorage(): Category[] {
  const data = localStorage.getItem(this.storageKey);
  return data ? JSON.parse(data) : [];
}

Visual Representation

Categories use Ionic’s color system and custom CSS:
getColorForUI(colorClass: string): string {
  switch(colorClass) {
    case 'realm-design': return 'primary';
    case 'realm-dev': return 'secondary';
    case 'realm-marketing': return 'warning';
    case 'realm-circle': return 'tertiary';
    case 'realm-innovation': return 'success';
    case 'realm-heal': return 'medium';
    case 'realm-study': return 'tertiary';
    case 'realm-funny': return 'warning';
    default: return 'primary';
  }
}

Next Steps

Quests

Learn how Quests use Categories for organization

Gamification

Discover how categories enhance the gamification experience

Build docs developers (and LLMs) love