From d3df8d8f7e532383afaa939e2e2e54379949baa1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 25 Mar 2026 22:25:58 +0000
Subject: [PATCH 1/3] Initial plan
From c52af557895a33d003fb13f1db8ce51c79640106 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 25 Mar 2026 22:41:28 +0000
Subject: [PATCH 2/3] Remove Reward Shop and Points features, auto-migrate
existing user data
Co-authored-by: JoeProgrammer88 <7156063+JoeProgrammer88@users.noreply.github.com>
Agent-Logs-Url: https://github.com/SpeakingInBits/TaskManagerWeb/sessions/4e268bbb-d824-4948-8ae1-c09a53cfee21
---
index.html | 69 ---------------
src/app.ts | 165 ------------------------------------
src/storage.ts | 190 +++++-------------------------------------
tests/storage.test.ts | 85 ++-----------------
4 files changed, 26 insertions(+), 483 deletions(-)
diff --git a/index.html b/index.html
index 5d6c76e..95eab40 100644
--- a/index.html
+++ b/index.html
@@ -26,10 +26,6 @@
-
diff --git a/src/app.ts b/src/app.ts
index de6e6b2..d78c6c7 100644
--- a/src/app.ts
+++ b/src/app.ts
@@ -23,7 +23,6 @@ class TaskManager {
currentEditingHabitId: string | null = null;
currentEditingFinanceId: string | null = null;
currentEditingFinanceType: string | null = null;
- currentEditingRewardId: string | null = null;
currentEditingWishItemId: string | null = null;
currentEditingNoteId: string | null = null;
dragSrcWishId: string | null = null;
@@ -132,12 +131,6 @@ class TaskManager {
document.getElementById('prevMonthBtn')!.addEventListener('click', () => this.navigateToPrevMonth());
document.getElementById('nextMonthBtn')!.addEventListener('click', () => this.navigateToNextMonth());
- // Shop section
- document.getElementById('addRewardBtn')!.addEventListener('click', () => this.openRewardModal());
- document.getElementById('rewardForm')!.addEventListener('submit', (e) => this.saveReward(e));
- document.getElementById('cancelRewardBtn')!.addEventListener('click', () => this.closeRewardModal());
- document.getElementById('deleteRewardBtn')!.addEventListener('click', () => this.deleteReward());
-
// Wish List section
document.getElementById('addWishItemBtn')!.addEventListener('click', () => this.openWishItemModal());
document.getElementById('wishItemForm')!.addEventListener('submit', (e) => this.saveWishItem(e));
@@ -262,8 +255,6 @@ class TaskManager {
this.renderHabits();
} else if (tabName === 'finances') {
this.renderFinances();
- } else if (tabName === 'shop') {
- this.renderShop();
} else if (tabName === 'wishlist') {
this.renderWishList();
} else if (tabName === 'notes') {
@@ -296,7 +287,6 @@ class TaskManager {
const userStats = storage.getUserStats();
// Update header stats
- document.getElementById('totalPoints')!.textContent = String(userStats.totalPoints);
document.getElementById('userLevel')!.textContent = String(userStats.level);
document.getElementById('dailyStreak')!.textContent = String(userStats.dailyStreak);
@@ -671,7 +661,6 @@ class TaskManager {
${task.dueDate ? `📅 ${task.dueDate}` : ''}
${task.priority}
${task.repeatType !== 'none' ? `🔁 ${task.repeatType}` : ''}
- ${task.points ? `⭐ ${task.points} pts` : ''}
${status}
@@ -715,7 +704,6 @@ class TaskManager {
(document.getElementById('taskDueDate') as HTMLInputElement).value = task.dueDate || '';
(document.getElementById('taskCategory') as HTMLSelectElement).value = task.category || '';
(document.getElementById('taskPriority') as HTMLSelectElement).value = task.priority || 'medium';
- (document.getElementById('taskPoints') as HTMLInputElement).value = String(task.points || 10);
(document.getElementById('taskRepeatType') as HTMLSelectElement).value = task.repeatType || 'none';
(document.getElementById('taskProject') as HTMLSelectElement).value = task.projectId || '';
(document.getElementById('taskRepeatUnit') as HTMLInputElement).value = String(task.repeatUnit || 1);
@@ -809,7 +797,6 @@ class TaskManager {
dueDate: (document.getElementById('taskDueDate') as HTMLInputElement).value,
category: (document.getElementById('taskCategory') as HTMLSelectElement).value,
priority: (document.getElementById('taskPriority') as HTMLSelectElement).value as Task['priority'],
- points: parseInt((document.getElementById('taskPoints') as HTMLInputElement).value),
repeatType: (document.getElementById('taskRepeatType') as HTMLSelectElement).value as Task['repeatType'],
projectId: (document.getElementById('taskProject') as HTMLSelectElement).value || null
};
@@ -857,7 +844,6 @@ class TaskManager {
task.completed = !task.completed;
if (task.completed) {
task.completedDate = this.getSelectedDateStr();
- storage.addPoints(task.points, 'tasks');
storage.updateDailyStreak(true);
// If repeatable, immediately create next task with recalculated due date
if (task.repeatType !== 'none') {
@@ -931,7 +917,6 @@ class TaskManager {
description: completedTask.description,
category: completedTask.category,
priority: completedTask.priority,
- points: completedTask.points,
projectId: completedTask.projectId,
repeatType: completedTask.repeatType,
repeatUnit: completedTask.repeatUnit,
@@ -1184,10 +1169,6 @@ class TaskManager {
Streak
${habit.streak || 0}
-
- Points
- ${habit.points}
-
Progress
${todaysCompletions}/${targetGoal}
@@ -1231,7 +1212,6 @@ class TaskManager {
(document.getElementById('habitIcon') as HTMLInputElement).value = habit.icon || '⭐';
document.getElementById('habitIconDisplay')!.textContent = habit.icon || '⭐';
(document.getElementById('habitCategory') as HTMLSelectElement).value = habit.category || '';
- (document.getElementById('habitPoints') as HTMLInputElement).value = String(habit.points || 5);
(document.getElementById('habitTargetGoal') as HTMLInputElement).value = String(habit.targetGoal || 1);
deleteBtn.style.display = 'block';
@@ -1274,7 +1254,6 @@ class TaskManager {
description: (document.getElementById('habitDescription') as HTMLTextAreaElement).value,
icon: (document.getElementById('habitIcon') as HTMLInputElement).value,
category: (document.getElementById('habitCategory') as HTMLSelectElement).value || null,
- points: parseInt((document.getElementById('habitPoints') as HTMLInputElement).value),
targetGoal: parseInt((document.getElementById('habitTargetGoal') as HTMLInputElement).value) || 1,
daysOfWeek: selectedDays.length > 0 ? selectedDays : [0, 1, 2, 3, 4, 5, 6]
};
@@ -1307,7 +1286,6 @@ class TaskManager {
if (isValidDay) {
storage.logHabitCompletion(habitId, this.selectedDate);
- storage.addPoints(habit.points, 'habits');
storage.updateDailyStreak(true);
this.renderHabits();
this.renderDashboard();
@@ -1730,149 +1708,6 @@ class TaskManager {
}
}
- // ========================
- // Shop/Rewards Management
- // ========================
- renderShop(): void {
- const rewards = storage.getRewards();
- const userStats = storage.getUserStats();
- const container = document.getElementById('rewardsList')!;
-
- document.getElementById('shopPointsDisplay')!.textContent = String(userStats.totalPoints);
-
- if (rewards.length === 0) {
- container.innerHTML = '
No rewards yet. Add rewards to spend your points on!
';
- return;
- }
-
- container.innerHTML = rewards.map(reward => {
- let alreadyPurchased = false;
- if (reward.repeatable === false) {
- const purchaseHistory = storage.getData().purchaseHistory || [];
- alreadyPurchased = purchaseHistory.some(ph => ph.rewardId === reward.id);
- }
- const disabled = userStats.totalPoints < reward.cost || alreadyPurchased;
- let purchaseLabel = 'Purchase';
- if (userStats.totalPoints < reward.cost) purchaseLabel = 'Not Enough Points';
- if (alreadyPurchased) purchaseLabel = 'Purchased';
-
- return `
-
-
${reward.name}
- ${reward.description ? `
${reward.description}
` : ''}
-
-
- Cost
- ${reward.cost} pts
-
-
- ${reward.repeatable === false ? 'One-time' : 'Repeatable'}
-
-
-
-
-
-
-
- `;
- }).join('');
-
- document.querySelectorAll('.purchase-btn').forEach(btn => {
- btn.addEventListener('click', (e) => {
- e.stopPropagation();
- const card = (e.target as HTMLElement).closest('[data-reward-id]') as HTMLElement;
- this.purchaseReward(card.dataset.rewardId!);
- });
- });
-
- document.querySelectorAll('.edit-reward-btn').forEach(btn => {
- btn.addEventListener('click', (e) => {
- e.stopPropagation();
- const card = (e.target as HTMLElement).closest('[data-reward-id]') as HTMLElement;
- this.openRewardModal(card.dataset.rewardId!);
- });
- });
- }
-
- openRewardModal(rewardId: string | null = null): void {
- this.currentEditingRewardId = rewardId;
- const modal = document.getElementById('rewardModal')!;
- const form = document.getElementById('rewardForm') as HTMLFormElement;
- const deleteBtn = document.getElementById('deleteRewardBtn') as HTMLElement;
-
- form.reset();
- deleteBtn.style.display = 'none';
-
- document.getElementById('rewardModalTitle')!.textContent = rewardId ? 'Edit Reward' : 'Add Reward';
-
- if (rewardId) {
- const reward = storage.getRewards().find(r => r.id === rewardId);
- if (reward) {
- (document.getElementById('rewardName') as HTMLInputElement).value = reward.name;
- (document.getElementById('rewardDescription') as HTMLTextAreaElement).value = reward.description || '';
- (document.getElementById('rewardCost') as HTMLInputElement).value = String(reward.cost);
- (document.getElementById('rewardRepeatable') as HTMLSelectElement).value = String(reward.repeatable === undefined ? true : reward.repeatable);
- deleteBtn.style.display = 'block';
- }
- }
-
- modal.classList.add('active');
- }
-
- closeRewardModal(): void {
- document.getElementById('rewardModal')!.classList.remove('active');
- this.currentEditingRewardId = null;
- }
-
- saveReward(e: Event): void {
- e.preventDefault();
-
- const reward = {
- name: (document.getElementById('rewardName') as HTMLInputElement).value,
- description: (document.getElementById('rewardDescription') as HTMLTextAreaElement).value,
- cost: parseInt((document.getElementById('rewardCost') as HTMLInputElement).value),
- repeatable: (document.getElementById('rewardRepeatable') as HTMLSelectElement).value === 'true'
- };
-
- if (this.currentEditingRewardId) {
- storage.updateReward(this.currentEditingRewardId, reward);
- } else {
- storage.addReward(reward);
- }
-
- this.closeRewardModal();
- this.renderShop();
- }
-
- deleteReward(): void {
- if (this.currentEditingRewardId) {
- if (confirm('Are you sure you want to delete this reward?')) {
- storage.deleteReward(this.currentEditingRewardId);
- this.closeRewardModal();
- this.renderShop();
- }
- }
- }
-
- purchaseReward(rewardId: string): void {
- const reward = storage.getRewards().find(r => r.id === rewardId);
- if (!reward) return;
-
- if (confirm(`Purchase "${reward.name}" for ${reward.cost} points?`)) {
- const result = storage.purchaseReward(rewardId);
-
- if (result.success) {
- alert(`Congratulations! You've purchased: ${reward.name}!\n\nEnjoy your reward! 🎉`);
- this.renderShop();
- this.renderDashboard();
- } else {
- alert(result.message);
- }
- }
- }
-
// ========================
// Wish List
// ========================
diff --git a/src/storage.ts b/src/storage.ts
index f0c033f..ef0fa53 100644
--- a/src/storage.ts
+++ b/src/storage.ts
@@ -4,7 +4,7 @@
const STORAGE_VERSION = '1.0.0';
const STORAGE_KEY = 'taskManagerData';
-const DATA_SCHEMA_VERSION = 1;
+const DATA_SCHEMA_VERSION = 2;
// ========================
// Type Definitions
@@ -17,7 +17,6 @@ export interface Task {
dueDate?: string;
category?: string | null;
priority: 'low' | 'medium' | 'high';
- points: number;
repeatType: 'none' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'custom' | 'movable';
repeatUnit?: number;
customRepeatDays?: number;
@@ -43,7 +42,6 @@ export interface Habit {
description?: string;
icon: string;
category?: string | null;
- points: number;
targetGoal: number;
daysOfWeek?: number[];
streak: number;
@@ -68,25 +66,6 @@ export interface FinanceItem {
createdDate: string;
}
-export interface Reward {
- id: string;
- name: string;
- description?: string;
- cost: number;
- repeatable: boolean;
- purchased: boolean;
- createdDate: string;
-}
-
-export interface Purchase {
- id: string;
- rewardId: string;
- rewardName: string;
- rewardDescription?: string;
- cost: number;
- purchaseDate: string;
-}
-
export interface WishItem {
id: string;
title: string;
@@ -105,20 +84,15 @@ export interface Note {
updatedDate?: string;
}
-export interface PointsBreakdown {
- tasks: number;
- projects: number;
- habits: number;
- streakBonus: number;
- [key: string]: number;
-}
-
export interface UserStats {
- totalPoints: number;
level: number;
dailyStreak: number;
lastActivityDate: string | null;
- pointsBreakdown: PointsBreakdown;
+}
+
+interface LegacyUserStats extends UserStats {
+ totalPoints?: number;
+ pointsBreakdown?: Record
;
}
export interface Settings {
@@ -136,8 +110,6 @@ export interface AppData {
expenses: FinanceItem[];
revenue: FinanceItem[];
charges: FinanceItem[];
- rewards: Reward[];
- purchaseHistory: Purchase[];
categories: string[];
userStats: UserStats;
settings: Settings;
@@ -145,12 +117,6 @@ export interface AppData {
notes: Note[];
}
-export interface PurchaseResult {
- success: boolean;
- message?: string;
- purchase?: Purchase;
-}
-
export interface ValidationResult {
isValid: boolean;
hasPartialData: boolean;
@@ -167,6 +133,16 @@ export class StorageManager {
const existingData = localStorage.getItem(STORAGE_KEY);
if (!existingData) {
this.createInitialData();
+ } else {
+ try {
+ const data = JSON.parse(existingData) as Partial;
+ if (!data.schemaVersion || data.schemaVersion < DATA_SCHEMA_VERSION) {
+ this.migrateToLatest();
+ }
+ } catch (e) {
+ console.error('Failed to read or migrate existing data:', e);
+ this.createInitialData();
+ }
}
}
@@ -182,20 +158,11 @@ export class StorageManager {
expenses: [],
revenue: [],
charges: [],
- rewards: [],
- purchaseHistory: [],
categories: ['Work', 'Personal', 'Home', 'Shopping', 'Health', 'Fitness', 'Learning', 'Productivity', 'Food', 'Transportation', 'Entertainment', 'Utilities', 'Income'],
userStats: {
- totalPoints: 0,
level: 1,
dailyStreak: 0,
- lastActivityDate: null,
- pointsBreakdown: {
- tasks: 0,
- projects: 0,
- habits: 0,
- streakBonus: 0
- }
+ lastActivityDate: null
},
settings: {
tasksPerLevel: 30
@@ -232,7 +199,6 @@ export class StorageManager {
completed: false,
title: task.title || '',
priority: task.priority || 'medium',
- points: task.points || 10,
repeatType: task.repeatType || 'none',
} as Task;
data.tasks.push(newTask);
@@ -315,7 +281,6 @@ export class StorageManager {
targetGoal: habit.targetGoal || 1,
name: habit.name || '',
icon: habit.icon || '⭐',
- points: habit.points || 10,
} as Habit;
data.habits.push(newHabit);
this.saveData(data);
@@ -535,103 +500,6 @@ export class StorageManager {
return data.charges || [];
}
- // Rewards Shop Management
- addReward(reward: Partial): Reward {
- const data = this.getData();
- if (!data.rewards) {
- data.rewards = [];
- }
- const newReward: Reward = {
- ...reward,
- id: this.generateId(),
- createdDate: new Date().toISOString(),
- purchased: false,
- repeatable: typeof reward.repeatable === 'undefined' ? true : reward.repeatable,
- name: reward.name || '',
- cost: reward.cost || 0,
- } as Reward;
- data.rewards.push(newReward);
- this.saveData(data);
- return newReward;
- }
-
- updateReward(rewardId: string, updates: Partial): Reward | undefined {
- const data = this.getData();
- if (!data.rewards) {
- data.rewards = [];
- }
- const reward = data.rewards.find(r => r.id === rewardId);
- if (reward) {
- Object.assign(reward, updates);
- if (typeof reward.repeatable === 'undefined') reward.repeatable = true;
- this.saveData(data);
- }
- return reward;
- }
-
- deleteReward(rewardId: string): void {
- const data = this.getData();
- if (!data.rewards) {
- data.rewards = [];
- }
- data.rewards = data.rewards.filter(r => r.id !== rewardId);
- this.saveData(data);
- }
-
- getRewards(): Reward[] {
- const data = this.getData();
- return data.rewards || [];
- }
-
- purchaseReward(rewardId: string): PurchaseResult {
- const data = this.getData();
- if (!data.rewards) {
- data.rewards = [];
- }
- if (!data.purchaseHistory) {
- data.purchaseHistory = [];
- }
-
- const reward = data.rewards.find(r => r.id === rewardId);
- if (!reward) {
- return { success: false, message: 'Reward not found' };
- }
-
- if (data.userStats.totalPoints < reward.cost) {
- return { success: false, message: 'Not enough points' };
- }
-
- // If one-time and already purchased, block
- if (reward.repeatable === false) {
- const alreadyPurchased = data.purchaseHistory.some(ph => ph.rewardId === reward.id);
- if (alreadyPurchased) {
- return { success: false, message: 'This reward can only be purchased once.' };
- }
- }
-
- // Deduct points
- data.userStats.totalPoints -= reward.cost;
-
- // Add to purchase history
- const purchase: Purchase = {
- id: this.generateId(),
- rewardId: reward.id,
- rewardName: reward.name,
- rewardDescription: reward.description,
- cost: reward.cost,
- purchaseDate: new Date().toISOString()
- };
- data.purchaseHistory.push(purchase);
-
- this.saveData(data);
- return { success: true, purchase };
- }
-
- getPurchaseHistory(): Purchase[] {
- const data = this.getData();
- return data.purchaseHistory || [];
- }
-
// Wish List Management
addWishItem(item: Partial): WishItem {
const data = this.getData();
@@ -726,18 +594,6 @@ export class StorageManager {
);
}
- // Points Management
- addPoints(amount: number, source: string): void {
- const data = this.getData();
- data.userStats.totalPoints += amount;
- if (data.userStats.pointsBreakdown[source] !== undefined) {
- data.userStats.pointsBreakdown[source] += amount;
- }
- // Level is now calculated based on completed tasks, not points
- this.updateLevel();
- this.saveData(data);
- }
-
updateLevel(): void {
const data = this.getData();
const settings = this.getSettings();
@@ -855,15 +711,11 @@ export class StorageManager {
expenses: Array.isArray(data.expenses) ? data.expenses : [],
revenue: Array.isArray(data.revenue) ? data.revenue : [],
charges: Array.isArray(data.charges) ? data.charges : [],
- rewards: Array.isArray(data.rewards) ? data.rewards : [],
- purchaseHistory: Array.isArray(data.purchaseHistory) ? data.purchaseHistory : [],
categories,
- userStats: data.userStats || {
- totalPoints: 0,
- level: 1,
- dailyStreak: 0,
- lastActivityDate: null,
- pointsBreakdown: { tasks: 0, projects: 0, habits: 0, streakBonus: 0 }
+ userStats: {
+ level: (data.userStats as LegacyUserStats)?.level ?? 1,
+ dailyStreak: (data.userStats as LegacyUserStats)?.dailyStreak ?? 0,
+ lastActivityDate: (data.userStats as LegacyUserStats)?.lastActivityDate ?? null,
},
settings: data.settings || { tasksPerLevel: 30 },
wishList: Array.isArray(data.wishList) ? data.wishList : [],
diff --git a/tests/storage.test.ts b/tests/storage.test.ts
index 678dbcb..3681e0c 100644
--- a/tests/storage.test.ts
+++ b/tests/storage.test.ts
@@ -1,6 +1,6 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { StorageManager, getDaysUntilDueText } from '../src/storage';
-import type { Task, Habit, FinanceItem, Reward } from '../src/storage';
+import type { Task, Habit, FinanceItem } from '../src/storage';
// Mock localStorage
const localStorageMock = (() => {
@@ -42,7 +42,6 @@ describe('StorageManager', () => {
expect(data.projects).toEqual([]);
expect(data.habits).toEqual([]);
expect(data.categories).toContain('Work');
- expect(data.userStats.totalPoints).toBe(0);
expect(data.userStats.level).toBe(1);
});
@@ -58,11 +57,10 @@ describe('StorageManager', () => {
// ========================
describe('task management', () => {
it('should add a task', () => {
- const task = storage.addTask({ title: 'Buy groceries', priority: 'high', points: 15 });
+ const task = storage.addTask({ title: 'Buy groceries', priority: 'high' });
expect(task.id).toBeDefined();
expect(task.title).toBe('Buy groceries');
expect(task.priority).toBe('high');
- expect(task.points).toBe(15);
expect(task.completed).toBe(false);
expect(task.createdDate).toBeDefined();
});
@@ -94,7 +92,6 @@ describe('StorageManager', () => {
it('should set default values for task fields', () => {
const task = storage.addTask({ title: 'Minimal' });
expect(task.priority).toBe('medium');
- expect(task.points).toBe(10);
expect(task.repeatType).toBe('none');
});
});
@@ -137,7 +134,7 @@ describe('StorageManager', () => {
// ========================
describe('habit management', () => {
it('should add a habit', () => {
- const habit = storage.addHabit({ name: 'Exercise', icon: '💪', points: 20 });
+ const habit = storage.addHabit({ name: 'Exercise', icon: '💪' });
expect(habit.id).toBeDefined();
expect(habit.name).toBe('Exercise');
expect(habit.streak).toBe(0);
@@ -335,81 +332,9 @@ describe('StorageManager', () => {
});
// ========================
- // Rewards Shop
+ // Leveling & Streak
// ========================
- describe('rewards shop', () => {
- it('should add a reward', () => {
- const reward = storage.addReward({ name: 'Movie Night', cost: 100 });
- expect(reward.id).toBeDefined();
- expect(reward.name).toBe('Movie Night');
- expect(reward.repeatable).toBe(true);
- expect(reward.purchased).toBe(false);
- });
-
- it('should update a reward', () => {
- const reward = storage.addReward({ name: 'Movie', cost: 100 });
- storage.updateReward(reward.id, { name: 'Movie Night', cost: 150 });
- const updated = storage.getRewards().find(r => r.id === reward.id);
- expect(updated?.name).toBe('Movie Night');
- expect(updated?.cost).toBe(150);
- });
-
- it('should delete a reward', () => {
- const reward = storage.addReward({ name: 'Movie Night', cost: 100 });
- storage.deleteReward(reward.id);
- expect(storage.getRewards().length).toBe(0);
- });
-
- it('should purchase a reward and deduct points', () => {
- storage.addPoints(200, 'tasks');
- const reward = storage.addReward({ name: 'Movie Night', cost: 100 });
- const result = storage.purchaseReward(reward.id);
- expect(result.success).toBe(true);
- expect(storage.getUserStats().totalPoints).toBe(100);
- expect(storage.getPurchaseHistory().length).toBe(1);
- });
-
- it('should fail to purchase with insufficient points', () => {
- const reward = storage.addReward({ name: 'Expensive', cost: 9999 });
- const result = storage.purchaseReward(reward.id);
- expect(result.success).toBe(false);
- expect(result.message).toBe('Not enough points');
- });
-
- it('should prevent re-purchasing one-time rewards', () => {
- storage.addPoints(500, 'tasks');
- const reward = storage.addReward({ name: 'One-time', cost: 100, repeatable: false });
- storage.purchaseReward(reward.id);
- const result = storage.purchaseReward(reward.id);
- expect(result.success).toBe(false);
- expect(result.message).toBe('This reward can only be purchased once.');
- });
-
- it('should allow re-purchasing repeatable rewards', () => {
- storage.addPoints(500, 'tasks');
- const reward = storage.addReward({ name: 'Repeatable', cost: 100, repeatable: true });
- storage.purchaseReward(reward.id);
- const result = storage.purchaseReward(reward.id);
- expect(result.success).toBe(true);
- });
-
- it('should fail for non-existent reward', () => {
- const result = storage.purchaseReward('nonexistent');
- expect(result.success).toBe(false);
- expect(result.message).toBe('Reward not found');
- });
- });
-
- // ========================
- // Points & Leveling
- // ========================
- describe('points and leveling', () => {
- it('should add points', () => {
- storage.addPoints(50, 'tasks');
- expect(storage.getUserStats().totalPoints).toBe(50);
- expect(storage.getUserStats().pointsBreakdown.tasks).toBe(50);
- });
-
+ describe('leveling and streak', () => {
it('should calculate level based on completed tasks', () => {
// Default: 30 tasks per level
for (let i = 0; i < 31; i++) {
From de093b64f6966d917f3e8093793bed832c3f7504 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 25 Mar 2026 22:55:10 +0000
Subject: [PATCH 3/3] Fix e2e tests: remove totalPoints check and rewards shop
test suite
Co-authored-by: JoeProgrammer88 <7156063+JoeProgrammer88@users.noreply.github.com>
Agent-Logs-Url: https://github.com/SpeakingInBits/TaskManagerWeb/sessions/ea6f881f-8324-488c-8ce2-efb4fa362fff
---
e2e/app.spec.ts | 34 +++-------------------------------
1 file changed, 3 insertions(+), 31 deletions(-)
diff --git a/e2e/app.spec.ts b/e2e/app.spec.ts
index 9cfde54..986771a 100644
--- a/e2e/app.spec.ts
+++ b/e2e/app.spec.ts
@@ -22,7 +22,6 @@ test.describe('Task Manager App', () => {
});
test('should display header stats', async ({ page }) => {
- await expect(page.locator('#totalPoints')).toHaveText('0');
await expect(page.locator('#userLevel')).toHaveText('1');
await expect(page.locator('#dailyStreak')).toHaveText('0');
});
@@ -236,31 +235,6 @@ test.describe('Task Manager App', () => {
});
});
- // ========================
- // Rewards Shop
- // ========================
- test.describe('rewards shop', () => {
- test.beforeEach(async ({ page }) => {
- await page.click('[data-tab="shop"]');
- });
-
- test('should show points display', async ({ page }) => {
- await expect(page.locator('#shopPointsDisplay')).toHaveText('0');
- });
-
- test('should create a reward', async ({ page }) => {
- await page.click('#addRewardBtn');
- await page.fill('#rewardName', 'Movie Night');
- await page.fill('#rewardDescription', 'Watch a movie');
- await page.fill('#rewardCost', '100');
- await page.click('#rewardForm button[type="submit"]');
-
- await expect(page.locator('#rewardModal')).not.toHaveClass(/active/);
- await expect(page.locator('.project-card')).toBeVisible();
- await expect(page.locator('.project-title')).toContainText('Movie Night');
- });
- });
-
// ========================
// Date Navigation
// ========================
@@ -319,7 +293,6 @@ test.describe('Task Manager App', () => {
title: 'Overdue Task',
dueDate: dueDate,
priority: 'medium',
- points: 10,
repeatType: 'none',
completed: false,
createdDate: new Date().toISOString()
@@ -346,7 +319,6 @@ test.describe('Task Manager App', () => {
title: 'Completed Old Task',
dueDate: dueDate,
priority: 'medium',
- points: 10,
repeatType: 'none',
completed: true,
completedDate: dueDate,
@@ -383,9 +355,9 @@ test.describe('Task Manager App', () => {
await page.evaluate(() => {
const data = JSON.parse(localStorage.getItem('taskManagerData') || '{}');
data.tasks = [
- { id: 'task-high', title: 'High Task', priority: 'high', points: 10, repeatType: 'none', completed: false, createdDate: new Date().toISOString(), category: 'Work' },
- { id: 'task-medium', title: 'Medium Task', priority: 'medium', points: 10, repeatType: 'none', completed: false, createdDate: new Date().toISOString(), category: 'Personal' },
- { id: 'task-low', title: 'Low Task', priority: 'low', points: 10, repeatType: 'none', completed: false, createdDate: new Date().toISOString() },
+ { id: 'task-high', title: 'High Task', priority: 'high', repeatType: 'none', completed: false, createdDate: new Date().toISOString(), category: 'Work' },
+ { id: 'task-medium', title: 'Medium Task', priority: 'medium', repeatType: 'none', completed: false, createdDate: new Date().toISOString(), category: 'Personal' },
+ { id: 'task-low', title: 'Low Task', priority: 'low', repeatType: 'none', completed: false, createdDate: new Date().toISOString() },
];
localStorage.setItem('taskManagerData', JSON.stringify(data));
});