diff --git a/apps/api/src/controllers/vote.Controller.ts b/apps/api/src/controllers/vote.Controller.ts index 4fee4bf..5d0e7e5 100644 --- a/apps/api/src/controllers/vote.Controller.ts +++ b/apps/api/src/controllers/vote.Controller.ts @@ -5,7 +5,7 @@ import { submitVote } from '../services/vote.Service' export const createVote = async (c: Context) => { const userId = c.get('userId') - + let body: VoteRequest try { body = await c.req.json() @@ -18,14 +18,14 @@ export const createVote = async (c: Context) => { if (typeof stallId !== 'number' || typeof rating !== 'number') { return c.json({ success: false, message: 'stallId and rating must be numbers' }, 400) } - + if (rating < 0 || rating > 10) { return c.json({ success: false, message: 'rating must be between 0 and 10' }, 400) } try { const progressCount = await submitVote(c.env, userId, body) - + const response: VoteResponse = { success: true, message: 'Vote submitted successfully', @@ -37,6 +37,9 @@ export const createVote = async (c: Context) => { if (e.message === 'Already voted') { return c.json({ success: false, message: 'Already voted' }, 400) } + if (e.message === 'Voting is currently closed') { + return c.json({ success: false, message: 'Voting is currently closed' }, 403) + } return c.json({ success: false, message: 'Internal Server Error' }, 500) } } diff --git a/apps/api/src/services/vote.Service.ts b/apps/api/src/services/vote.Service.ts index 43e2e3d..ada8d94 100644 --- a/apps/api/src/services/vote.Service.ts +++ b/apps/api/src/services/vote.Service.ts @@ -5,11 +5,41 @@ import { eq, count } from 'drizzle-orm' import type { AppEnv } from '../types' import { ensureUserExists } from './user.Service' import { refreshStallAggregates } from './stalls.Service' +function isVotingOpen(): boolean { + const istOffset = 5.5 * 60 * 60 * 1000; + const istTime = new Date(Date.now() + istOffset); + + const year = istTime.getUTCFullYear(); + const month = istTime.getUTCMonth() + 1; + const day = istTime.getUTCDate(); + + if (year !== 2026 || month !== 3) return false; + + const timeInMinutes = istTime.getUTCHours() * 60 + istTime.getUTCMinutes(); + const startMins = 9 * 60 + 30; // 9:30 AM (570) + + if (day === 28) { + const endMins = 22 * 60; // 10:00 PM (1320) + return timeInMinutes >= startMins && timeInMinutes <= endMins; + } + + if (day === 29) { + const endMins = 12 * 60; // 12:00 PM (720) + return timeInMinutes >= startMins && timeInMinutes <= endMins; + } + + return false; +} + export const submitVote = async ( env: AppEnv['Bindings'], userId: string, vote: VoteRequest ) => { + if (!isVotingOpen()) { + throw new Error('Voting is currently closed'); + } + const { stallId, rating } = vote const ormDb = getDb(env.DB) @@ -49,11 +79,11 @@ export const submitVote = async ( .select({ stallId: ratings.stallId }) .from(ratings) .where(eq(ratings.userId, userId)); - + const stallIds = userRatings .map(r => r.stallId) .filter((id): id is number => id !== null); - + await refreshStallAggregates(env.DB, stallIds); } else { // Normal vote (could be qualified or not, but only this stall is affected)