Add timezone-aware schedule window

master
John Montagu, the 4th Earl of Sandvich 2024-11-07 17:58:26 -08:00
parent fc6092d282
commit 1bf4cc3125
Signed by: sandvich
GPG Key ID: 9A39BE37E602B22D
6 changed files with 74 additions and 14 deletions

View File

@ -5,6 +5,8 @@
export type TeamSchema = {
discordWebhookUrl?: string;
id: number;
minuteOffset: number;
teamName: string;
tzTimezone: string;
};

View File

@ -0,0 +1,31 @@
import { beforeEach, describe, expect, it } from "vitest";
import { useScheduleStore } from "./schedule";
import { createPinia, setActivePinia } from "pinia";
describe("Schedule store", () => {
beforeEach(() => {
setActivePinia(createPinia());
});
it("should return the proper window start for any timezone", () => {
const scheduleStore = useScheduleStore();
let test1 = scheduleStore.getWindowStart({
teamName: "",
id: 0,
tzTimezone: "Asia/Kolkata",
minuteOffset: 10,
});
expect(test1.get("minutes")).toEqual(40);
let test2 = scheduleStore.getWindowStart({
teamName: "",
id: 0,
tzTimezone: "America/New_York",
minuteOffset: 30,
});
expect(test2.get("minutes")).toEqual(30);
});
});

View File

@ -3,6 +3,9 @@ import { defineStore } from "pinia";
import { reactive, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useClientStore } from "./client";
import type { TeamSchema } from "@/client";
import moment from "moment";
import "moment-timezone";
export const useScheduleStore = defineStore("schedule", () => {
const client = useClientStore().client;
@ -18,23 +21,43 @@ export const useScheduleStore = defineStore("schedule", () => {
const route = useRoute();
const router = useRouter();
const teamId = computed({
get: () => Number(route.query.teamId),
set: (value) => router.push({ query: { teamId: value } }),
});
//const teamId = computed({
// get: () => Number(route?.query?.teamId),
// set: (value) => router.push({ query: { teamId: value } }),
//});
const team = ref();
function getWindowStart(team: TeamSchema) {
// convert local 00:00 to league timezone
let localMidnight = moment().startOf("isoWeek");
let leagueTime = localMidnight.clone().tz(team.tz_timezone);
let nextMinuteOffsetTime = leagueTime.clone();
if (nextMinuteOffsetTime.minute() > team.minute_offset) {
nextMinuteOffsetTime.add(1, "hour");
}
nextMinuteOffsetTime.minute(team.minute_offset);
const deltaMinutes = nextMinuteOffsetTime.diff(leagueTime, "minutes");
return localMidnight.clone().add(deltaMinutes, "minutes");
}
watch(dateStart, () => {
fetchSchedule();
});
watch(teamId, () => {
fetchSchedule();
watch(team, () => {
dateStart.value = getWindowStart(team.value).toDate();
console.log(dateStart.value);
});
async function fetchSchedule() {
return client.default.getApiSchedule(
Math.floor(dateStart.value.getTime() / 1000).toString(),
teamId.value,
team.value.id,
)
.then((response) => {
response.availability.forEach((value, i) => {
@ -60,7 +83,7 @@ export const useScheduleStore = defineStore("schedule", () => {
async function saveSchedule() {
return client.default.putApiSchedule({
windowStart: Math.floor(dateStart.value.getTime() / 1000).toString(),
teamId: teamId.value,
teamId: team.value.id,
availability,
});
//return fetch(import.meta.env.VITE_API_BASE_URL + "/schedule", {
@ -83,6 +106,7 @@ export const useScheduleStore = defineStore("schedule", () => {
availability,
fetchSchedule,
saveSchedule,
teamId,
team,
getWindowStart,
};
});

View File

@ -30,7 +30,7 @@ const selectedTeam = ref();
watch(selectedTeam, (newTeam) => {
if (newTeam) {
schedule.teamId = newTeam.id;
schedule.team = newTeam;
}
});
@ -47,11 +47,10 @@ onMounted(() => {
options.value = Object.values(teamsList.teams);
// select team with id in query parameter if exists
const queryTeam = teamsList.teams.find(x => x.id == route.query.teamId);
console.log(queryTeam);
if (queryTeam) {
selectedTeam.value = queryTeam;
//schedule.teamId = queryTeam.id;
schedule.fetchSchedule(schedule.teamId);
schedule.team = queryTeam;
schedule.fetchSchedule();
}
});
});

View File

@ -57,6 +57,8 @@ class TeamSchema(spec.BaseModel):
id: int
team_name: str
discord_webhook_url: str | None
tz_timezone: str
minute_offset: int
#players: list[PlayerTeamSpec] | None
class PlayerTeam(db.Model):

View File

@ -20,7 +20,9 @@ def map_team_to_schema(team: Team):
return TeamSchema(
id=team.id,
team_name=team.team_name,
discord_webhook_url=None
discord_webhook_url=None,
tz_timezone=team.tz_timezone,
minute_offset=team.minute_offset
)
def map_player_to_schema(player: Player):