mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-09 12:46:10 -05:00
Fix flexible time scrim notif time and sidebar show logic
This commit is contained in:
@@ -20,6 +20,40 @@ const WINDOW = {
|
||||
endTime: dbTs(add(BOOKED_AT, { hours: 1 })),
|
||||
};
|
||||
|
||||
/**
|
||||
* A "flexible time" post whose window opened `windowOpensInMinutes` from now,
|
||||
* booked by a request that picked a start `bookedInMinutes` from now.
|
||||
*/
|
||||
async function createBookedRangeScrim({
|
||||
windowOpensInMinutes,
|
||||
bookedInMinutes,
|
||||
}: {
|
||||
windowOpensInMinutes: number;
|
||||
bookedInMinutes: number;
|
||||
}) {
|
||||
const now = new Date();
|
||||
const bookedAt = add(now, { minutes: bookedInMinutes });
|
||||
|
||||
const { id } = await ScrimPostFactory.create(
|
||||
{
|
||||
startsAt: dbTs(add(now, { minutes: windowOpensInMinutes })),
|
||||
rangeEndsAt: dbTs(add(now, { minutes: windowOpensInMinutes + 120 })),
|
||||
users: [{ userId: users.id(1), isOwner: 1 }],
|
||||
},
|
||||
{
|
||||
requests: [
|
||||
{
|
||||
startsAt: dbTs(bookedAt),
|
||||
users: [{ userId: users.id(2), isOwner: 1 }],
|
||||
isAccepted: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
return { id, bookedAt: dbTs(bookedAt) };
|
||||
}
|
||||
|
||||
describe("findPendingOverlapsForUsers", () => {
|
||||
beforeEach(async () => {
|
||||
await users.create(5);
|
||||
@@ -251,6 +285,68 @@ describe("findUserScrims", () => {
|
||||
expect(postOwnerScrims).toHaveLength(1);
|
||||
expect(postOwnerScrims[0]!.status).toBe("booked");
|
||||
});
|
||||
|
||||
test("lists a booked range scrim whose post window opened before the booked start", async () => {
|
||||
const { id } = await createBookedRangeScrim({
|
||||
windowOpensInMinutes: -30,
|
||||
bookedInMinutes: 45,
|
||||
});
|
||||
|
||||
const scrims = await ScrimPostRepository.findUserScrims(users.id(1));
|
||||
|
||||
expect(scrims.map((scrim) => scrim.id)).toContain(id);
|
||||
});
|
||||
|
||||
test("reports the booked start of a range scrim, not the start of its window", async () => {
|
||||
const { id, bookedAt } = await createBookedRangeScrim({
|
||||
windowOpensInMinutes: 30,
|
||||
bookedInMinutes: 90,
|
||||
});
|
||||
|
||||
const scrims = await ScrimPostRepository.findUserScrims(users.id(2));
|
||||
const scrim = scrims.find((scrim) => scrim.id === id);
|
||||
|
||||
expect(scrim?.status).toBe("booked");
|
||||
expect(scrim?.startsAt).toBe(bookedAt);
|
||||
});
|
||||
});
|
||||
|
||||
describe("findAcceptedScrimsBetweenTwoTimestamps", () => {
|
||||
beforeEach(async () => {
|
||||
await users.create(2);
|
||||
});
|
||||
|
||||
const startingWithinTheHour = async () => {
|
||||
const now = new Date();
|
||||
|
||||
return ScrimPostRepository.findAcceptedScrimsBetweenTwoTimestamps({
|
||||
startTime: now,
|
||||
endTime: add(now, { hours: 1 }),
|
||||
excludeRecentlyCreated: add(now, { minutes: 1 }),
|
||||
});
|
||||
};
|
||||
|
||||
test("finds a range scrim booked to start inside the window", async () => {
|
||||
const { id } = await createBookedRangeScrim({
|
||||
windowOpensInMinutes: -30,
|
||||
bookedInMinutes: 45,
|
||||
});
|
||||
|
||||
const scrims = await startingWithinTheHour();
|
||||
|
||||
expect(scrims.map((scrim) => scrim.id)).toContain(id);
|
||||
});
|
||||
|
||||
test("leaves out a range scrim booked to start after the window", async () => {
|
||||
const { id } = await createBookedRangeScrim({
|
||||
windowOpensInMinutes: 30,
|
||||
bookedInMinutes: 120,
|
||||
});
|
||||
|
||||
const scrims = await startingWithinTheHour();
|
||||
|
||||
expect(scrims.map((scrim) => scrim.id)).not.toContain(id);
|
||||
});
|
||||
});
|
||||
|
||||
describe("insertRequest", () => {
|
||||
|
||||
@@ -239,6 +239,9 @@ const baseFindQuery = db
|
||||
).as("requests"),
|
||||
]);
|
||||
|
||||
/** The booked start of a scrim: the accepted request's chosen time for a range post, the post's own otherwise. */
|
||||
const bookedStartsAt = sql<number>`coalesce((select "ScrimPostRequest"."startsAt" from "ScrimPostRequest" where "ScrimPostRequest"."scrimPostId" = "ScrimPost"."id" and "ScrimPostRequest"."isAccepted" = 1), "ScrimPost"."startsAt")`;
|
||||
|
||||
function findMany() {
|
||||
const min = sub(new Date(), { hours: 3 });
|
||||
|
||||
@@ -541,8 +544,8 @@ export async function findAcceptedScrimsBetweenTwoTimestamps({
|
||||
excludeRecentlyCreated: Date;
|
||||
}) {
|
||||
const rows = await baseFindQuery
|
||||
.where("ScrimPost.startsAt", ">=", dateToDatabaseTimestamp(startTime))
|
||||
.where("ScrimPost.startsAt", "<", dateToDatabaseTimestamp(endTime))
|
||||
.where(bookedStartsAt, ">=", dateToDatabaseTimestamp(startTime))
|
||||
.where(bookedStartsAt, "<", dateToDatabaseTimestamp(endTime))
|
||||
.where("ScrimPost.canceledAt", "is", null)
|
||||
.where(
|
||||
"ScrimPost.createdAt",
|
||||
@@ -711,7 +714,7 @@ export async function findUserScrims(userId: number): Promise<SidebarScrim[]> {
|
||||
|
||||
const rows = await baseFindQuery
|
||||
.where("ScrimPost.canceledAt", "is", null)
|
||||
.where("ScrimPost.startsAt", ">=", now)
|
||||
.where(bookedStartsAt, ">=", now)
|
||||
.where((eb) =>
|
||||
eb.or([
|
||||
eb.exists(
|
||||
@@ -735,7 +738,7 @@ export async function findUserScrims(userId: number): Promise<SidebarScrim[]> {
|
||||
),
|
||||
]),
|
||||
)
|
||||
.orderBy("ScrimPost.startsAt", "asc")
|
||||
.orderBy(bookedStartsAt, "asc")
|
||||
.execute();
|
||||
|
||||
return rows
|
||||
|
||||
5
changelog/2026-09-02-flexible-scrim-booked-time.md
Normal file
5
changelog/2026-09-02-flexible-scrim-booked-time.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
navItem: scrims
|
||||
type: bug
|
||||
---
|
||||
Booked scrims from "flexible time" posts now stay on your events list until their booked start, and the "starting soon" notification is sent at the right time
|
||||
Reference in New Issue
Block a user