Skip to content

Conversation

@hamizfaraz
Copy link
Collaborator

@hamizfaraz hamizfaraz commented Jan 10, 2026

PR Type

Enhancement


Description

  • Implement gamification system with points, ranks, and progression tracking

  • Add task points calculation based on priority and deadline completion timing

  • Integrate rank progression UI with visual indicators and modal display

  • Expand task filtering to include overdue and unscheduled categories

  • Display earned points rewards when completing tasks with animations


Diagram Walkthrough

flowchart LR
  A["Task Completion"] -->|"calculateEarnedPoints"| B["Earned Points"]
  B -->|"updateUserPoints"| C["User Points Updated"]
  C -->|"getRankProgress"| D["Rank & Progress"]
  D -->|"Display in UI"| E["StatsWidget & Rewards"]
  F["Task Priority"] -->|"getPointsForPriority"| B
  G["Task Deadline"] -->|"Bonus/Penalty"| B
Loading

File Walkthrough

Relevant files
Enhancement
9 files
gamification.ts
New gamification library with points and rank system         
+112/-0 
route.ts
Add points calculation to task creation pipeline                 
+2/-0     
userService.ts
Add updatePoints method for user point management               
+25/-0   
taskService.ts
Support earned_points field in task updates                           
+1/-0     
index.ts
Expose updateUserPoints through API service                           
+1/-0     
StatsWidget.tsx
Display rank progress with visual indicators and modal     
+156/-16
TasksPage.tsx
Calculate and update earned points on task completion       
+47/-15 
TaskFilters.tsx
Add overdue and unscheduled task filter options                   
+7/-3     
TaskList.tsx
Display earned points rewards with animations on completion
+146/-135

@vercel
Copy link

vercel bot commented Jan 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
taskmaster-frontend Error Error Jan 10, 2026 4:52am

@qodo-code-review
Copy link

qodo-code-review bot commented Jan 10, 2026

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Points integrity bypass

Description: updatePoints(delta) allows the client to submit an arbitrary points delta and performs a
non-atomic read-modify-write (select('points') then update({ points: nextPoints })), which
can enable points tampering (e.g., sending large positive deltas) and/or lost-update
exploits under concurrent requests unless server-side authorization/RLS and an atomic
increment (RPC/SQL increment) are enforced.
userService.ts [10-33]

Referred Code
async updatePoints(delta: number): Promise<number> {
  const userId = await getCachedUserId();

  const { data: current, error: fetchError } = await supabase
    .from('users')
    .select('points')
    .eq('id', userId)
    .single();

  if (fetchError) throw new Error(fetchError.message);

  const nextPoints = Math.max(0, (current?.points || 0) + delta);

  const { data: updated, error: updateError } = await supabase
    .from('users')
    .update({ points: nextPoints })
    .eq('id', userId)
    .select('points')
    .single();

  if (updateError) throw new Error(updateError.message);


 ... (clipped 3 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Missing audit logging: The new updatePoints flow updates persisted user points without emitting any audit log
entry that includes user id, action, timestamp, and outcome.

Referred Code
async updatePoints(delta: number): Promise<number> {
  const userId = await getCachedUserId();

  const { data: current, error: fetchError } = await supabase
    .from('users')
    .select('points')
    .eq('id', userId)
    .single();

  if (fetchError) throw new Error(fetchError.message);

  const nextPoints = Math.max(0, (current?.points || 0) + delta);

  const { data: updated, error: updateError } = await supabase
    .from('users')
    .update({ points: nextPoints })
    .eq('id', userId)
    .select('points')
    .single();

  if (updateError) throw new Error(updateError.message);


 ... (clipped 3 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Swallowed points errors: The points update failure is caught and only console.error is executed, leaving the
UI/state potentially inconsistent without a recovery or user-visible handling path.

Referred Code
  try {
    const nextPoints = await apiService.updateUserPoints(pointsDelta);
    setUserState({ points: nextPoints });
  } catch (pointsError) {
    console.error("Error updating points:", pointsError);
  }
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Leaky user error: The UI sets setError(error.message ...), which can expose internal/Supabase error details
directly to end users.

Referred Code
} catch (error: any) {
  console.error("Error updating task:", error);
  setTasks(previousTasks);
  setError(error.message || "Failed to update task");
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Unstructured console logs: New console.error logging of raw error objects is unstructured and may inadvertently
include sensitive details from backend responses.

Referred Code
  console.error("Error updating points:", pointsError);
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Authorization not visible: The new updatePoints method performs a direct update of users.points based on
getCachedUserId() without any explicit authorization/ownership check shown in the diff,
which may be unsafe depending on Supabase RLS policies.

Referred Code
async updatePoints(delta: number): Promise<number> {
  const userId = await getCachedUserId();

  const { data: current, error: fetchError } = await supabase
    .from('users')
    .select('points')
    .eq('id', userId)
    .single();

  if (fetchError) throw new Error(fetchError.message);

  const nextPoints = Math.max(0, (current?.points || 0) + delta);

  const { data: updated, error: updateError } = await supabase
    .from('users')
    .update({ points: nextPoints })
    .eq('id', userId)
    .select('points')
    .single();

  if (updateError) throw new Error(updateError.message);


 ... (clipped 3 lines)

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link

qodo-code-review bot commented Jan 10, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Prevent race conditions during point updates

Refactor the updatePoints function to use a Supabase RPC function. This will
perform the point update atomically in the database, preventing race conditions
and potential data loss from concurrent requests.

taskmaster-client/src/services/api/userService.ts [10-33]

 export const userService = {
   async addHamizAsFriend(): Promise<any> {
     return { message: "Hamiz Iqbal added as friend successfully" };
   },
 
   async updatePoints(delta: number): Promise<number> {
     const userId = await getCachedUserId();
 
-    const { data: current, error: fetchError } = await supabase
-      .from('users')
-      .select('points')
-      .eq('id', userId)
-      .single();
+    const { data, error } = await supabase.rpc('increment_user_points', {
+      user_id_input: userId,
+      points_delta: delta,
+    });
 
-    if (fetchError) throw new Error(fetchError.message);
+    if (error) {
+      throw new Error(`Failed to update points: ${error.message}`);
+    }
 
-    const nextPoints = Math.max(0, (current?.points || 0) + delta);
-
-    const { data: updated, error: updateError } = await supabase
-      .from('users')
-      .update({ points: nextPoints })
-      .eq('id', userId)
-      .select('points')
-      .single();
-
-    if (updateError) throw new Error(updateError.message);
-
-    return updated?.points ?? nextPoints;
+    return data as number;
   },
 
   async matchFriends(userId: string): Promise<{ users: string[] }> {
     // Find users with similar preferences for friend matching
     // ...
   },
 };

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical race condition in the updatePoints function and proposes a robust, standard solution using an atomic database operation to ensure data integrity.

High
Merge user state updates

When updating user points, merge the new points with the previous user state
instead of overwriting the entire user object. Use the functional form of
setUserState to ensure other user properties are preserved.

taskmaster-client/src/client-pages/tasks/TasksPage.tsx [103-126]

-const previousTasks = tasks;
+const previousTasks = [...tasks];
 ...
 if (pointsDelta !== 0) {
   try {
     const nextPoints = await apiService.updateUserPoints(pointsDelta);
-    setUserState({ points: nextPoints });
+    setUserState(prev => ({ ...prev, points: nextPoints }));
   } catch (pointsError) {
     console.error("Error updating points:", pointsError);
   }
 }

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 8

__

Why: This is a critical fix. The current code replaces the entire user object when updating points, which would discard all other user data. The suggestion correctly advises merging the new points into the existing state to prevent data loss.

Medium
Guard against missing Supabase

Add a check at the beginning of the POST handler to verify that the supabase
client is initialized. If it is not, return a 500 error to prevent runtime
errors later in the function.

taskmaster-client/src/app/api/documents/analyze-azure/route.ts [210-216]

-export async function POST(req: NextRequest) {
-  // Check critical config
-  if (!DOC_INTEL_ENDPOINT || !DOC_INTEL_KEY) {
-    return NextResponse.json({ error: 'Azure Document Intelligence not configured.' }, { status: 500 });
-  }
+// Check critical config
+if (!DOC_INTEL_ENDPOINT || !DOC_INTEL_KEY) {
+  return NextResponse.json({ error: 'Azure Document Intelligence not configured.' }, { status: 500 });
+}
+if (!supabase) {
+  return NextResponse.json({ error: 'Supabase not configured.' }, { status: 500 });
+}
 
-  let body;
+let body;

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 6

__

Why: The suggestion correctly points out a missing check for the supabase client initialization. Adding this guard improves robustness by failing early with a clear error message if the configuration is missing.

Low
General
Use a single source for points

Refactor the userPoints calculation to rely solely on currentUser?.points. This
avoids potential UI flicker and data inconsistency caused by comparing a locally
calculated taskPoints with a potentially stale global user state.

taskmaster-client/src/client-pages/dashboard/StatsWidget.tsx [108-114]

-const taskPoints = tasks.reduce((total, task) => {
-  const isComplete = task.completed || task.status === "completed";
-  if (!isComplete) return total;
-  const points = task.earnedPoints ?? task.points ?? 0;
-  return total + (Number.isFinite(points) ? points : 0);
-}, 0);
-const userPoints = Math.max(taskPoints, currentUser?.points || 0);
+const userPoints = currentUser?.points || 0;
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a potential UI inconsistency by using two different sources for user points and proposes simplifying the logic to use the currentUser context as the single source of truth, improving data consistency.

Medium
  • Update

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants