Skip to content

Commit 60f6513

Browse files
committed
Refactor: Remove Activity model and related code
- Deleted the Activity model and its references in the profileController and userCacheService. - Updated profileRoutes to remove the getUserActivity endpoint. - Cleaned up userCacheService by removing caching methods for user activity. - Adjusted profileController to streamline user profile management. Enhancement: Introduce timezone utility functions - Added timezone.js with utility functions for handling IST (Indian Standard Time). - Implemented functions to get IST date bounds, format dates, and check if timestamps fall within today or yesterday in IST. - Updated challengeController, platformsController, and postPOTD utility to utilize new timezone functions for date handling. Improvement: Optimize challenge and user streak logic - Refactored challengeController and postPOTD to use new timezone utilities for date comparisons. - Simplified logic for checking if challenges were solved today or yesterday based on IST. Cleanup: Remove unused imports and comments - Removed commented-out code and unnecessary imports across various controllers and middleware for better readability. - Cleaned up error handling and logging in middleware to reduce clutter.
1 parent a6f0e53 commit 60f6513

File tree

19 files changed

+172
-299
lines changed

19 files changed

+172
-299
lines changed

client-test/src/components/ProfilePage/index.tsx

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,13 @@ export default function ProfilePage() {
8080
const [error, setError] = useState(null)
8181
const [selectedYear, setSelectedYear] = useState(new Date().getFullYear())
8282

83-
// Account deletion modal states
83+
8484
const [showDeleteModal, setShowDeleteModal] = useState(false)
8585
const [showConfirmation, setShowConfirmation] = useState(false)
8686
const [usernameInput, setUsernameInput] = useState("")
8787
const [isDeleting, setIsDeleting] = useState(false)
8888
const [deleteError, setDeleteError] = useState("")
8989

90-
// Create a derived heatmap from solveChallenges
9190
const generateHeatmapFromSolveChallenges = (user: ProfileUser | null) => {
9291
if (!user || !user.solveChallenges) return []
9392

@@ -300,7 +299,6 @@ export default function ProfilePage() {
300299
)
301300
}
302301

303-
// Calculate the number of problems solved in each difficulty using the solveChallenges object
304302
const problemsSolved = {
305303
total:
306304
(profileUser.solveChallenges?.easy?.length || 0) +
@@ -311,7 +309,6 @@ export default function ProfilePage() {
311309
hard: profileUser.solveChallenges?.hard?.length || 0,
312310
}
313311

314-
// Generate the heatmap data from solveChallenges
315312
const heatmap = generateHeatmapFromSolveChallenges(profileUser)
316313

317314
interface GetDaysInMonthParams {
@@ -327,18 +324,6 @@ export default function ProfilePage() {
327324
count: number
328325
}
329326

330-
const generateContributions = (year: number): Contribution[] => {
331-
const contributions: Contribution[] = []
332-
const startDate = new Date(year, 0, 1)
333-
const endDate = new Date(year, 11, 31)
334-
for (let date = new Date(startDate); date <= endDate; date.setDate(date.getDate() + 1)) {
335-
const count = Math.random() > 0.6 ? Math.floor(Math.random() * 10) : 0
336-
contributions.push({ date: date.toISOString().split("T")[0], count })
337-
}
338-
return contributions
339-
}
340-
341-
const contributions = generateContributions(selectedYear)
342327
const yearOptions = [new Date().getFullYear(), new Date().getFullYear() - 1, new Date().getFullYear() - 2]
343328

344329
interface StreakParams {
@@ -353,14 +338,31 @@ export default function ProfilePage() {
353338
const currentCount = currentContrib ? currentContrib.count : 0
354339
if (currentCount === 0) return false
355340

341+
// Check previous day
356342
const prevDate = new Date(currentDate)
357343
prevDate.setDate(prevDate.getDate() - 1)
358-
const prevContrib = contributions.find((c) => c.date === prevDate.toISOString().split("T")[0])
344+
const prevDateString = prevDate.toISOString().split("T")[0]
345+
const prevContrib = heatmap.find((item) => {
346+
if (item.timestamp) {
347+
const itemDate = new Date(item.timestamp).toISOString().split("T")[0]
348+
return itemDate === prevDateString
349+
}
350+
return false
351+
})
352+
353+
// Check next day
359354
const nextDate = new Date(currentDate)
360355
nextDate.setDate(nextDate.getDate() + 1)
361-
const nextContrib = contributions.find((c) => c.date === nextDate.toISOString().split("T")[0])
356+
const nextDateString = nextDate.toISOString().split("T")[0]
357+
const nextContrib = heatmap.find((item) => {
358+
if (item.timestamp) {
359+
const itemDate = new Date(item.timestamp).toISOString().split("T")[0]
360+
return itemDate === nextDateString
361+
}
362+
return false
363+
})
362364

363-
return (prevContrib?.count ?? 0) > 0 || (nextContrib?.count ?? 0) > 0
365+
return (prevContrib ? 1 : 0) > 0 || (nextContrib ? 1 : 0) > 0
364366
}
365367

366368
const containerVariants = {

server/controllers/authController.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import jwt from "jsonwebtoken"
22
import bcrypt from "bcryptjs";
33
import crypto from "crypto"; // For generating OTP
44
import { User } from "../models/User.js"
5-
import { Activity } from "../models/Activity.js"
65
import { sendOTPEmail, deleteConfirmationMail, sendResetPassEmail } from "../utils/emailService.js"
76
import { isEmailValid } from "../utils/isEmailValid.js";
87
import mongoose from "mongoose";

server/controllers/challengeController.js

Lines changed: 6 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { fetchLeetCodeStatus, fetchCodeforcesStatus } from "./platformsControlle
55
import { postPotdChallenge } from "../utils/postPOTD.js";
66
import auditService from "../services/auditService.js";
77
import { Category } from '../models/Category.js';
8+
import { getISTDateBounds, formatISTDateTimeString } from '../utils/timezone.js';
89

910
export const getChallenges = async (req, res) => {
1011
try {
@@ -54,12 +55,7 @@ export const getChallenges = async (req, res) => {
5455
}
5556

5657
// Date filter for challenges (exclude today's POTD)
57-
const now = new Date();
58-
const istOffset = 5.5 * 60 * 60 * 1000; // IST is UTC+5:30
59-
const istNow = new Date(now.getTime() + istOffset);
60-
const today = new Date(istNow);
61-
today.setHours(0, 0, 0, 0);
62-
const todayUTC = new Date(today.getTime() - istOffset);
58+
const { start: todayUTC } = getISTDateBounds();
6359
filter.createdAt = { $lt: todayUTC };
6460

6561
// Build aggregation pipeline for better performance
@@ -149,19 +145,8 @@ export const getDailyChallenge = async (req, res) => {
149145
const { userId } = req.query;
150146
const authenticatedUser = req.user;
151147

152-
// Create today's date in IST timezone
153-
const now = new Date();
154-
const istOffset = 5.5 * 60 * 60 * 1000; // IST is UTC+5:30
155-
const istNow = new Date(now.getTime() + istOffset);
156-
157-
const today = new Date(istNow);
158-
today.setHours(0, 0, 0, 0);
159-
const tomorrow = new Date(today);
160-
tomorrow.setDate(tomorrow.getDate() + 1);
161-
162-
// Convert back to UTC for database query
163-
const todayUTC = new Date(today.getTime() - istOffset);
164-
const tomorrowUTC = new Date(tomorrow.getTime() - istOffset);
148+
// Get today's IST date boundaries (returns UTC dates for database query)
149+
const { start: todayUTC, end: tomorrowUTC } = getISTDateBounds();
165150

166151
let dailyChallenge = await Challenge.findOne({
167152
createdAt: {
@@ -332,32 +317,8 @@ export const checkPOTDStatus = async (req, res) => {
332317
}
333318

334319
if (responseStatus && responseStatus.success) {
335-
const now = new Intl.DateTimeFormat("en-IN", {
336-
timeZone: "Asia/Kolkata",
337-
year: "numeric",
338-
month: "2-digit",
339-
day: "2-digit",
340-
hour: "2-digit",
341-
minute: "2-digit",
342-
second: "2-digit",
343-
hour12: false,
344-
}).formatToParts(new Date());
345-
346-
let year = "", month = "", day = "", hour = "", minute = "", second = "";
347-
348-
now.forEach(part => {
349-
if (part.type === "year") year = part.value;
350-
if (part.type === "month") month = part.value;
351-
if (part.type === "day") day = part.value;
352-
if (part.type === "hour") hour = part.value;
353-
if (part.type === "minute") minute = part.value;
354-
if (part.type === "second") second = part.value;
355-
});
356-
357-
const timestamp = {
358-
date: `${year}-${month}-${day}`,
359-
time: `${hour}:${minute}:${second}`
360-
};
320+
// Use timezone utility to format IST timestamp
321+
const timestamp = formatISTDateTimeString();
361322

362323
const postresponse = await postPotdChallenge(userId, timestamp, dailyChallengeId, dailyChallenge.difficulty);
363324
if (postresponse.success) {

server/controllers/platformsController.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { fetchCodeforcesProfile, fetchLeetCodeProfile } from "../lib/leetcode.js
55
import { Challenge } from "../models/Challenge.js";
66
import { getGFGName } from "../utils/gfgService.js";
77
import auditService from "../services/auditService.js";
8+
import { formatISTDateString, isWithinTodayIST } from '../utils/timezone.js';
89
export const leetcodeData = async (req, res) => {
910
try {
1011
const username = req.body.username; // Get username from request body
@@ -352,10 +353,10 @@ export const fetchLeetCodeStatus = async (username, challengeTitle) => {
352353
throw new Error("No submissions found");
353354
}
354355

355-
const today = new Date().toLocaleDateString("en-IN", { timeZone: "Asia/Kolkata" }).split('/').reverse().join('-');
356-
356+
const today = formatISTDateString();
357+
357358
const solvedToday = recentSubmissionList.some(submission => {
358-
const submissionDate = new Date(parseInt(submission.timestamp) * 1000).toLocaleDateString("en-IN", { timeZone: "Asia/Kolkata" }).split('/').reverse().join('-');
359+
const submissionDate = formatISTDateString(new Date(parseInt(submission.timestamp) * 1000));
359360
return submission.title === challengeTitle && submission.statusDisplay === "Accepted" && submissionDate === today;
360361
});
361362

@@ -380,10 +381,10 @@ export const fetchCodeforcesStatus = async (username, challengeTitle) => {
380381
return { success: false, message: "Invalid Codeforces username or no submissions found" };
381382
}
382383

383-
const today = new Date().toLocaleDateString("en-IN", { timeZone: "Asia/Kolkata" }).split('/').reverse().join('-');
384+
const today = formatISTDateString();
384385

385386
const solvedProblem = submissions.result.find((submission) => {
386-
const submissionDate = new Date(submission.creationTimeSeconds * 1000).toLocaleDateString("en-IN", { timeZone: "Asia/Kolkata" }).split('/').reverse().join('-');
387+
const submissionDate = formatISTDateString(new Date(submission.creationTimeSeconds * 1000));
387388
return submission.problem.name === challengeTitle && submission.verdict === "OK" && submissionDate === today;
388389
});
389390

0 commit comments

Comments
 (0)