From 22777c6363ff5f65629ae0865ce7027dc80cca77 Mon Sep 17 00:00:00 2001 From: Jayesh Kharode Date: Tue, 25 Aug 2026 14:58:48 +0530 Subject: [PATCH] Fix custom date visibility and apply range on profile (#98) Co-authored-by: Cursor Signed-off-by: Jayesh Kharode Co-authored-by: Cursor --- .../backend/routes/userDetailsRoute.js | 14 +++--- .../backend/services/userDetailsService.js | 46 +++++++++++++------ github-activity-tracker/frontend/src/App.tsx | 4 ++ .../frontend/src/components/TopNav.tsx | 4 +- .../frontend/src/components/UserProfile.tsx | 42 +++++++++++++---- .../frontend/src/lib/api.ts | 4 +- 6 files changed, 82 insertions(+), 32 deletions(-) diff --git a/github-activity-tracker/backend/routes/userDetailsRoute.js b/github-activity-tracker/backend/routes/userDetailsRoute.js index 070f414..e088e84 100644 --- a/github-activity-tracker/backend/routes/userDetailsRoute.js +++ b/github-activity-tracker/backend/routes/userDetailsRoute.js @@ -2,18 +2,20 @@ const express = require('express'); const router = express.Router(); const { getUserDetails } = require('../services/userDetailsService'); const { resolveRoleFilter } = require('../services/userRolesService'); +const { resolvePeriodQuery } = require('../utils/dateRange'); -// GET /orgs/:org_id/users/:login?period=daily|weekly|monthly|yearly&role=Developer +// GET /orgs/:org_id/users/:login?period=daily|weekly|monthly|yearly|custom&role=Developer router.get('/orgs/:org_id/users/:login', async (req, res) => { const { org_id, login } = req.params; - const { period = 'weekly', role } = req.query; + const { role } = req.query; + const { error: periodError, period, startDate, endDate } = resolvePeriodQuery(req.query); if (!login) { return res.status(400).json({ error: 'Missing user login' }); } - if (!['daily', 'weekly', 'monthly', 'yearly'].includes(period)) { - return res.status(400).json({ error: 'Invalid period value' }); + if (periodError) { + return res.status(400).json({ error: periodError }); } try { @@ -22,7 +24,7 @@ router.get('/orgs/:org_id/users/:login', async (req, res) => { return res.status(400).json({ error }); } - const data = await getUserDetails(org_id, login, period, roleFilter); + const data = await getUserDetails(org_id, login, period, roleFilter, startDate, endDate); return res.json(data); } catch (err) { console.error('Error in User Details API:', err); @@ -30,4 +32,4 @@ router.get('/orgs/:org_id/users/:login', async (req, res) => { } }); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/github-activity-tracker/backend/services/userDetailsService.js b/github-activity-tracker/backend/services/userDetailsService.js index 0951fd4..5fc0747 100644 --- a/github-activity-tracker/backend/services/userDetailsService.js +++ b/github-activity-tracker/backend/services/userDetailsService.js @@ -2,6 +2,7 @@ const dayjs = require('dayjs'); const pool = require('../db/dbPool'); const { isExcludedGitHubLogin } = require('../config/excludedGitHubLogins'); const { userDetailsJoinSql } = require('../utils/userRoleSql'); +const { getCustomDateRange } = require('../utils/dateRange'); /* ------------------------------------------------ Helper: Calculate % change @@ -14,7 +15,7 @@ function percentChange(current, previous) { /* ------------------------------------------------ MAIN SERVICE ------------------------------------------------ */ -async function getUserDetails(orgId, login, period, role = null) { +async function getUserDetails(orgId, login, period, role = null, startDate, endDate) { if (isExcludedGitHubLogin(login)) { throw new Error('User not found'); } @@ -42,22 +43,37 @@ async function getUserDetails(orgId, login, period, role = null) { const userId = user.id; /* 2. Determine date ranges */ - const periods = { - daily: 1, - weekly: 7, - monthly: 30, - yearly: 365, - }; + let start; + let end; + let prevStart; + let prevEnd; + let days; + + if (period === 'custom') { + const range = getCustomDateRange(startDate, endDate); + start = dayjs(range.start); + end = dayjs(range.end); + prevStart = dayjs(range.prevStart); + prevEnd = dayjs(range.prevEnd); + days = range.days; + } else { + const periods = { + daily: 1, + weekly: 7, + monthly: 30, + yearly: 365, + }; - const days = periods[period]; - if (!days) { - throw new Error('Invalid period'); - } + days = periods[period]; + if (!days) { + throw new Error('Invalid period'); + } - const end = dayjs().endOf('day'); - const start = end.subtract(days - 1, 'day').startOf('day'); - const prevEnd = start.subtract(1, 'millisecond'); - const prevStart = prevEnd.subtract(days - 1, 'day').startOf('day'); + end = dayjs().endOf('day'); + start = end.subtract(days - 1, 'day').startOf('day'); + prevEnd = start.subtract(1, 'millisecond'); + prevStart = prevEnd.subtract(days - 1, 'day').startOf('day'); + } const orgOwner = String(orgId).toLowerCase(); diff --git a/github-activity-tracker/frontend/src/App.tsx b/github-activity-tracker/frontend/src/App.tsx index 8f7db55..7418c14 100644 --- a/github-activity-tracker/frontend/src/App.tsx +++ b/github-activity-tracker/frontend/src/App.tsx @@ -186,6 +186,10 @@ function App() { org={selectedOrg} userName={selectedUser} onBack={() => setActivePage("dashboard")} + period={period} + startDate={startDate} + endDate={endDate} + onPeriodChange={handlePeriodChange} /> )} diff --git a/github-activity-tracker/frontend/src/components/TopNav.tsx b/github-activity-tracker/frontend/src/components/TopNav.tsx index 7e7c0d4..9b8baf9 100644 --- a/github-activity-tracker/frontend/src/components/TopNav.tsx +++ b/github-activity-tracker/frontend/src/components/TopNav.tsx @@ -235,7 +235,7 @@ const TopNav: React.FC = ({ value={draftStart} max={draftEnd || undefined} onChange={(e) => setDraftStart(e.target.value)} - className="w-full mb-3 px-3 py-2 border rounded-lg bg-white text-sm" + className="w-full mb-3 px-3 py-2 border rounded-lg bg-white text-gray-900 text-sm" />