feat: schedule automatic form closure

This commit is contained in:
2026-07-31 00:54:15 +07:00 Unverified
parent 8ee011cdfc
commit 6a73b60c48
20 changed files with 1226 additions and 35 deletions
+7 -4
View File
@@ -68,6 +68,9 @@ export async function getAdminDashboardData(
const tomorrowStartSql = toPostgresTimestamp(tomorrowStart);
const last7DaysStartSql = toPostgresTimestamp(last7DaysStart);
const totalResponses = sql<number>`count(${submissions.id})::integer`;
const acceptingSubmissions = sql<boolean>`${forms.isOpen} and (
${forms.closesAt} is null or ${forms.closesAt} > ${now}
)`;
const responsesToday = sql<number>`count(${submissions.id}) filter (
where ${submissions.submittedAt} >= ${todayStartSql}::timestamp
and ${submissions.submittedAt} < ${tomorrowStartSql}::timestamp
@@ -82,8 +85,8 @@ export async function getAdminDashboardData(
db
.select({
totalForms: sql<number>`count(*)::integer`,
openForms: sql<number>`count(*) filter (where ${forms.isOpen})::integer`,
closedForms: sql<number>`count(*) filter (where not ${forms.isOpen})::integer`,
openForms: sql<number>`count(*) filter (where ${acceptingSubmissions})::integer`,
closedForms: sql<number>`count(*) filter (where not (${acceptingSubmissions}))::integer`,
})
.from(forms),
db
@@ -117,7 +120,7 @@ export async function getAdminDashboardData(
.select({
id: forms.id,
title: forms.title,
isOpen: forms.isOpen,
isOpen: acceptingSubmissions,
totalResponses,
responsesToday,
responsesLast7Days,
@@ -125,7 +128,7 @@ export async function getAdminDashboardData(
})
.from(forms)
.leftJoin(submissions, eq(submissions.formId, forms.id))
.groupBy(forms.id, forms.title, forms.isOpen, forms.createdAt)
.groupBy(forms.id, forms.title, forms.isOpen, forms.closesAt, forms.createdAt)
.orderBy(
desc(responsesLast7Days),
desc(totalResponses),
+37
View File
@@ -0,0 +1,37 @@
import { describe, expect, test } from "bun:test";
import { isFormAcceptingSubmissions } from "@/lib/form-availability";
const now = new Date("2026-07-30T12:00:00.000Z");
describe("isFormAcceptingSubmissions", () => {
test("keeps a manually open form without a deadline open", () => {
expect(isFormAcceptingSubmissions({ isOpen: true }, now)).toBe(true);
});
test("keeps a form open before its deadline", () => {
expect(
isFormAcceptingSubmissions(
{ isOpen: true, closesAt: "2026-07-30T12:00:01.000Z" },
now,
),
).toBe(true);
});
test("closes a form when its deadline is reached", () => {
expect(
isFormAcceptingSubmissions(
{ isOpen: true, closesAt: "2026-07-30T12:00:00.000Z" },
now,
),
).toBe(false);
});
test("manual closure overrides a future deadline", () => {
expect(
isFormAcceptingSubmissions(
{ isOpen: false, closesAt: "2026-08-01T12:00:00.000Z" },
now,
),
).toBe(false);
});
});
+14
View File
@@ -0,0 +1,14 @@
export type FormAvailability = {
isOpen: boolean;
closesAt?: Date | string | null;
};
export function isFormAcceptingSubmissions(
form: FormAvailability,
now = new Date(),
) {
if (!form.isOpen) return false;
if (!form.closesAt) return true;
return new Date(form.closesAt).getTime() > now.getTime();
}