Add timezone-aware schedule window
parent
fc6092d282
commit
1bf4cc3125
|
@ -5,6 +5,8 @@
|
||||||
export type TeamSchema = {
|
export type TeamSchema = {
|
||||||
discordWebhookUrl?: string;
|
discordWebhookUrl?: string;
|
||||||
id: number;
|
id: number;
|
||||||
|
minuteOffset: number;
|
||||||
teamName: string;
|
teamName: string;
|
||||||
|
tzTimezone: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,6 +3,9 @@ import { defineStore } from "pinia";
|
||||||
import { reactive, ref, watch } from "vue";
|
import { reactive, ref, watch } from "vue";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { useClientStore } from "./client";
|
import { useClientStore } from "./client";
|
||||||
|
import type { TeamSchema } from "@/client";
|
||||||
|
import moment from "moment";
|
||||||
|
import "moment-timezone";
|
||||||
|
|
||||||
export const useScheduleStore = defineStore("schedule", () => {
|
export const useScheduleStore = defineStore("schedule", () => {
|
||||||
const client = useClientStore().client;
|
const client = useClientStore().client;
|
||||||
|
@ -18,23 +21,43 @@ export const useScheduleStore = defineStore("schedule", () => {
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const teamId = computed({
|
//const teamId = computed({
|
||||||
get: () => Number(route.query.teamId),
|
// get: () => Number(route?.query?.teamId),
|
||||||
set: (value) => router.push({ query: { teamId: value } }),
|
// 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, () => {
|
watch(dateStart, () => {
|
||||||
fetchSchedule();
|
fetchSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(teamId, () => {
|
watch(team, () => {
|
||||||
fetchSchedule();
|
dateStart.value = getWindowStart(team.value).toDate();
|
||||||
|
console.log(dateStart.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function fetchSchedule() {
|
async function fetchSchedule() {
|
||||||
return client.default.getApiSchedule(
|
return client.default.getApiSchedule(
|
||||||
Math.floor(dateStart.value.getTime() / 1000).toString(),
|
Math.floor(dateStart.value.getTime() / 1000).toString(),
|
||||||
teamId.value,
|
team.value.id,
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
response.availability.forEach((value, i) => {
|
response.availability.forEach((value, i) => {
|
||||||
|
@ -60,7 +83,7 @@ export const useScheduleStore = defineStore("schedule", () => {
|
||||||
async function saveSchedule() {
|
async function saveSchedule() {
|
||||||
return client.default.putApiSchedule({
|
return client.default.putApiSchedule({
|
||||||
windowStart: Math.floor(dateStart.value.getTime() / 1000).toString(),
|
windowStart: Math.floor(dateStart.value.getTime() / 1000).toString(),
|
||||||
teamId: teamId.value,
|
teamId: team.value.id,
|
||||||
availability,
|
availability,
|
||||||
});
|
});
|
||||||
//return fetch(import.meta.env.VITE_API_BASE_URL + "/schedule", {
|
//return fetch(import.meta.env.VITE_API_BASE_URL + "/schedule", {
|
||||||
|
@ -83,6 +106,7 @@ export const useScheduleStore = defineStore("schedule", () => {
|
||||||
availability,
|
availability,
|
||||||
fetchSchedule,
|
fetchSchedule,
|
||||||
saveSchedule,
|
saveSchedule,
|
||||||
teamId,
|
team,
|
||||||
|
getWindowStart,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,7 +30,7 @@ const selectedTeam = ref();
|
||||||
|
|
||||||
watch(selectedTeam, (newTeam) => {
|
watch(selectedTeam, (newTeam) => {
|
||||||
if (newTeam) {
|
if (newTeam) {
|
||||||
schedule.teamId = newTeam.id;
|
schedule.team = newTeam;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -47,11 +47,10 @@ onMounted(() => {
|
||||||
options.value = Object.values(teamsList.teams);
|
options.value = Object.values(teamsList.teams);
|
||||||
// select team with id in query parameter if exists
|
// select team with id in query parameter if exists
|
||||||
const queryTeam = teamsList.teams.find(x => x.id == route.query.teamId);
|
const queryTeam = teamsList.teams.find(x => x.id == route.query.teamId);
|
||||||
console.log(queryTeam);
|
|
||||||
if (queryTeam) {
|
if (queryTeam) {
|
||||||
selectedTeam.value = queryTeam;
|
selectedTeam.value = queryTeam;
|
||||||
//schedule.teamId = queryTeam.id;
|
schedule.team = queryTeam;
|
||||||
schedule.fetchSchedule(schedule.teamId);
|
schedule.fetchSchedule();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -57,6 +57,8 @@ class TeamSchema(spec.BaseModel):
|
||||||
id: int
|
id: int
|
||||||
team_name: str
|
team_name: str
|
||||||
discord_webhook_url: str | None
|
discord_webhook_url: str | None
|
||||||
|
tz_timezone: str
|
||||||
|
minute_offset: int
|
||||||
#players: list[PlayerTeamSpec] | None
|
#players: list[PlayerTeamSpec] | None
|
||||||
|
|
||||||
class PlayerTeam(db.Model):
|
class PlayerTeam(db.Model):
|
||||||
|
|
|
@ -20,7 +20,9 @@ def map_team_to_schema(team: Team):
|
||||||
return TeamSchema(
|
return TeamSchema(
|
||||||
id=team.id,
|
id=team.id,
|
||||||
team_name=team.team_name,
|
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):
|
def map_player_to_schema(player: Player):
|
||||||
|
|
Loading…
Reference in New Issue