fix: made payday overlay only go away when iuncome detected
All checks were successful
Deploy / deploy (push) Successful in 1m31s
Security Tests / security-non-db (push) Successful in 22s
Security Tests / security-db (push) Successful in 27s

This commit is contained in:
2026-03-28 21:37:36 -05:00
parent cb87c906c8
commit 339ab559d1

View File

@@ -4,6 +4,8 @@ import { z } from "zod";
import { fromZonedTime } from "date-fns-tz"; import { fromZonedTime } from "date-fns-tz";
import { getUserMidnight } from "../allocator.js"; import { getUserMidnight } from "../allocator.js";
const DAY_MS = 24 * 60 * 60 * 1000;
type RateLimitRouteOptions = { type RateLimitRouteOptions = {
config: { config: {
rateLimit: { rateLimit: {
@@ -100,15 +102,42 @@ const paydayRoutes: FastifyPluginAsync<PaydayRoutesOptions> = async (app, opts)
userTimezone userTimezone
); );
const isPayday = isWithinPaydayWindow(now, nextPayday, 0, userTimezone); const isPayday = isWithinPaydayWindow(now, nextPayday, 0, userTimezone);
const dayStart = getUserMidnight(userTimezone, now);
const dayEnd = new Date(dayStart.getTime() + 24 * 60 * 60 * 1000 - 1); // Determine the currently due pay cycle:
const scheduledIncomeToday = await app.prisma.incomeEvent.findFirst({ // - on payday: cycle starts today
// - after payday: cycle starts on the last expected payday
const lookbackDaysByFrequency = {
weekly: 14,
biweekly: 28,
monthly: 62,
} as const;
const lookbackAnchor = new Date(
now.getTime() - lookbackDaysByFrequency[user.incomeFrequency] * DAY_MS
);
const currentCycleStart = calculateNextPayday(
user.firstIncomeDate,
user.incomeFrequency,
lookbackAnchor,
userTimezone
);
const isCycleDue = now.getTime() >= currentCycleStart.getTime();
const currentCycleEnd =
currentCycleStart.getTime() === nextPayday.getTime()
? calculateNextPayday(
user.firstIncomeDate,
user.incomeFrequency,
new Date(nextPayday.getTime() + DAY_MS),
userTimezone
)
: nextPayday;
const scheduledIncomeInCurrentCycle = await app.prisma.incomeEvent.findFirst({
where: { where: {
userId, userId,
isScheduledIncome: true, isScheduledIncome: true,
postedAt: { postedAt: {
gte: dayStart, gte: currentCycleStart,
lte: dayEnd, lt: currentCycleEnd,
}, },
}, },
select: { id: true }, select: { id: true },
@@ -120,14 +149,17 @@ const paydayRoutes: FastifyPluginAsync<PaydayRoutesOptions> = async (app, opts)
firstIncomeDate: user.firstIncomeDate.toISOString(), firstIncomeDate: user.firstIncomeDate.toISOString(),
nextPayday: nextPayday.toISOString(), nextPayday: nextPayday.toISOString(),
isPayday, isPayday,
currentCycleStart: currentCycleStart.toISOString(),
currentCycleEnd: currentCycleEnd.toISOString(),
isCycleDue,
pendingScheduledIncome: user.pendingScheduledIncome, pendingScheduledIncome: user.pendingScheduledIncome,
scheduledIncomeToday: !!scheduledIncomeToday, scheduledIncomeInCurrentCycle: !!scheduledIncomeInCurrentCycle,
shouldShowOverlay: isPayday && !scheduledIncomeToday, shouldShowOverlay: isCycleDue && !scheduledIncomeInCurrentCycle,
}); });
return { return {
shouldShowOverlay: isPayday && !scheduledIncomeToday, shouldShowOverlay: isCycleDue && !scheduledIncomeInCurrentCycle,
pendingScheduledIncome: !scheduledIncomeToday, pendingScheduledIncome: !scheduledIncomeInCurrentCycle,
nextPayday: nextPayday.toISOString(), nextPayday: nextPayday.toISOString(),
}; };
}); });