From 102cbebdb5fec1a1a29bb8c5f8b61ebab19d633f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 31 Jan 2026 11:17:56 +0000 Subject: [PATCH 1/5] Initial plan From 3f7e455076f1f508bf42ca2bac3980e4e88a3371 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 31 Jan 2026 11:20:39 +0000 Subject: [PATCH 2/5] Fix issues 1 & 2: default time and add button Co-authored-by: fredli74 <6632456+fredli74@users.noreply.github.com> --- app/src/components/schedule-item.vue | 4 ++-- app/src/components/vehicle-schedule.vue | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/components/schedule-item.vue b/app/src/components/schedule-item.vue index 0e7f3b08..0e9b48d6 100644 --- a/app/src/components/schedule-item.vue +++ b/app/src/components/schedule-item.vue @@ -174,7 +174,7 @@ export default class ScheduleItem extends Vue { const dt = this.localSchedule.time || new Date( - Math.ceil(Date.now() / 60e4) * 60e4 + 12 * 60 * 60e3 + Math.ceil((Date.now() + 60 * 60e3) / (10 * 60e3)) * (10 * 60e3) ).toISOString(); return DateTime.fromISO(dt).toLocal(); } @@ -210,7 +210,7 @@ export default class ScheduleItem extends Vue { async addSchedule() { this.isSaving = true; - this.$emit(`add`, () => { + this.$emit(`add`, this.localSchedule, () => { this.isSaving = false; }); } diff --git a/app/src/components/vehicle-schedule.vue b/app/src/components/vehicle-schedule.vue index 19dcfde4..f7377d6e 100644 --- a/app/src/components/vehicle-schedule.vue +++ b/app/src/components/vehicle-schedule.vue @@ -53,11 +53,11 @@ export default class VehicleSchedule extends Vue { mounted() {} data() { + // Default to 1 hour in the future, rounded to nearest 10 minutes + const defaultTime = Math.ceil((Date.now() + 60 * 60e3) / (10 * 60e3)) * (10 * 60e3); return { schedule: undefined, - guideDateTime: DateTime.fromMillis( - Math.ceil(Date.now() / 60e4) * 60e4 + 12 * 60 * 60e3 - ), + guideDateTime: DateTime.fromMillis(defaultTime), newSchedule: undefined, }; } @@ -87,16 +87,16 @@ export default class VehicleSchedule extends Vue { }; } - async addSchedule(callback: any) { - if (this.newSchedule && this.newSchedule.type) { - const lvl = this.newSchedule.level || null; + async addSchedule(localSchedule: Partial, callback: any) { + if (localSchedule && localSchedule.type) { + const lvl = localSchedule.level || null; const time = - (this.newSchedule.time && new Date(this.newSchedule.time)) || null; + (localSchedule.time && new Date(localSchedule.time)) || null; await this.$scClient.updateSchedule( undefined, this.vehicle.id, - this.newSchedule.type, + localSchedule.type, lvl, time ); From 393771c1d43143c0c2387d15bab522d1a6ba9c61 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 31 Jan 2026 11:21:41 +0000 Subject: [PATCH 3/5] Fix issue 3: enable charge level editing for new schedules Co-authored-by: fredli74 <6632456+fredli74@users.noreply.github.com> --- app/src/components/schedule-item.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/components/schedule-item.vue b/app/src/components/schedule-item.vue index 0e9b48d6..c6055169 100644 --- a/app/src/components/schedule-item.vue +++ b/app/src/components/schedule-item.vue @@ -188,7 +188,9 @@ export default class ScheduleItem extends Vue { async setLevel() { this.localSchedule.level = this.levelSlider; this.levelMenu = false; - await this.save(); + if (!this.newSchedule) { + await this.save(); + } } get directLevel(): number { const settings = getVehicleLocationSettings(this.vehicle); @@ -203,7 +205,7 @@ export default class ScheduleItem extends Vue { } else { this.localSchedule.time = datetime.toJSDate().toISOString(); } - if (this.localSchedule.time !== was) { + if (this.localSchedule.time !== was && !this.newSchedule) { await this.save(); } } From f1b23ae1ca33374d7a2f3f6eabb52dd24428fd9b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 31 Jan 2026 11:23:31 +0000 Subject: [PATCH 4/5] Refactor: extract default time calculation to shared utility Co-authored-by: fredli74 <6632456+fredli74@users.noreply.github.com> --- app/src/components/schedule-item.vue | 6 ++---- app/src/components/vehicle-schedule.vue | 5 ++--- shared/utils.ts | 11 +++++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/app/src/components/schedule-item.vue b/app/src/components/schedule-item.vue index c6055169..43bab781 100644 --- a/app/src/components/schedule-item.vue +++ b/app/src/components/schedule-item.vue @@ -134,7 +134,7 @@ import { Component, Vue, Prop } from "vue-property-decorator"; import { GQLSchedule, GQLScheduleType, GQLVehicle } from "@shared/sc-schema.js"; import { DateTime } from "luxon"; import { DatetimePopup } from "vue-datetime"; -import { relativeTime } from "@shared/utils.js"; +import { relativeTime, getDefaultScheduleTime } from "@shared/utils.js"; import { getVehicleLocationSettings } from "@shared/sc-utils.js"; @Component({ components: { DatetimePopup } }) @@ -173,9 +173,7 @@ export default class ScheduleItem extends Vue { get scheduleDateTime(): DateTime { const dt = this.localSchedule.time || - new Date( - Math.ceil((Date.now() + 60 * 60e3) / (10 * 60e3)) * (10 * 60e3) - ).toISOString(); + new Date(getDefaultScheduleTime()).toISOString(); return DateTime.fromISO(dt).toLocal(); } stopCapture() { diff --git a/app/src/components/vehicle-schedule.vue b/app/src/components/vehicle-schedule.vue index f7377d6e..b7edeba9 100644 --- a/app/src/components/vehicle-schedule.vue +++ b/app/src/components/vehicle-schedule.vue @@ -34,6 +34,7 @@ import { Component, Vue, Prop, Watch } from "vue-property-decorator"; import { DateTime } from "luxon"; import { GQLVehicle, GQLSchedule, GQLScheduleType } from "@shared/sc-schema.js"; +import { getDefaultScheduleTime } from "@shared/utils.js"; import ScheduleItem from "./schedule-item.vue"; @Component({ components: { ScheduleItem } }) @@ -53,11 +54,9 @@ export default class VehicleSchedule extends Vue { mounted() {} data() { - // Default to 1 hour in the future, rounded to nearest 10 minutes - const defaultTime = Math.ceil((Date.now() + 60 * 60e3) / (10 * 60e3)) * (10 * 60e3); return { schedule: undefined, - guideDateTime: DateTime.fromMillis(defaultTime), + guideDateTime: DateTime.fromMillis(getDefaultScheduleTime()), newSchedule: undefined, }; } diff --git a/shared/utils.ts b/shared/utils.ts index 1d52b671..e2da36cb 100644 --- a/shared/utils.ts +++ b/shared/utils.ts @@ -234,6 +234,17 @@ export function capitalize(s: string): string { return s.charAt(0).toUpperCase() + s.slice(1); } +/** + * Gets the default schedule time for a new schedule. + * Returns current time + 1 hour, rounded to the nearest 10 minutes. + * @returns Time in milliseconds since epoch + */ +export function getDefaultScheduleTime(): number { + const TEN_MINUTES_IN_MS = 10 * 60 * 1000; + const ONE_HOUR_IN_MS = 60 * 60 * 1000; + return Math.ceil((Date.now() + ONE_HOUR_IN_MS) / TEN_MINUTES_IN_MS) * TEN_MINUTES_IN_MS; +} + /** * Computes the differences between two objects and returns the properties From dc91e83be70d9440754022f3b0337959771ad781 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 31 Jan 2026 11:39:29 +0000 Subject: [PATCH 5/5] Fix issue 1 correctly: prevent past AI schedule times from being used Co-authored-by: fredli74 <6632456+fredli74@users.noreply.github.com> --- app/src/components/schedule-item.vue | 6 ++++-- app/src/components/vehicle-schedule.vue | 13 ++++++++----- shared/utils.ts | 11 ----------- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/app/src/components/schedule-item.vue b/app/src/components/schedule-item.vue index 43bab781..33b986d3 100644 --- a/app/src/components/schedule-item.vue +++ b/app/src/components/schedule-item.vue @@ -134,7 +134,7 @@ import { Component, Vue, Prop } from "vue-property-decorator"; import { GQLSchedule, GQLScheduleType, GQLVehicle } from "@shared/sc-schema.js"; import { DateTime } from "luxon"; import { DatetimePopup } from "vue-datetime"; -import { relativeTime, getDefaultScheduleTime } from "@shared/utils.js"; +import { relativeTime } from "@shared/utils.js"; import { getVehicleLocationSettings } from "@shared/sc-utils.js"; @Component({ components: { DatetimePopup } }) @@ -173,7 +173,9 @@ export default class ScheduleItem extends Vue { get scheduleDateTime(): DateTime { const dt = this.localSchedule.time || - new Date(getDefaultScheduleTime()).toISOString(); + new Date( + Math.ceil(Date.now() / 60e4) * 60e4 + 12 * 60 * 60e3 + ).toISOString(); return DateTime.fromISO(dt).toLocal(); } stopCapture() { diff --git a/app/src/components/vehicle-schedule.vue b/app/src/components/vehicle-schedule.vue index b7edeba9..dc42f1d0 100644 --- a/app/src/components/vehicle-schedule.vue +++ b/app/src/components/vehicle-schedule.vue @@ -34,7 +34,6 @@ import { Component, Vue, Prop, Watch } from "vue-property-decorator"; import { DateTime } from "luxon"; import { GQLVehicle, GQLSchedule, GQLScheduleType } from "@shared/sc-schema.js"; -import { getDefaultScheduleTime } from "@shared/utils.js"; import ScheduleItem from "./schedule-item.vue"; @Component({ components: { ScheduleItem } }) @@ -56,7 +55,9 @@ export default class VehicleSchedule extends Vue { data() { return { schedule: undefined, - guideDateTime: DateTime.fromMillis(getDefaultScheduleTime()), + guideDateTime: DateTime.fromMillis( + Math.ceil(Date.now() / 60e4) * 60e4 + 12 * 60 * 60e3 + ), newSchedule: undefined, }; } @@ -69,9 +70,11 @@ export default class VehicleSchedule extends Vue { if (f.type === GQLScheduleType.Trip) return true; if (f.type === GQLScheduleType.Manual) return true; if (f.type === GQLScheduleType.AI) { - this.guideDateTime = DateTime.fromMillis( - Math.ceil(new Date(f.time).getTime() / 60e4) * 60e4 - ); + const aiTime = Math.ceil(new Date(f.time).getTime() / 60e4) * 60e4; + // Only use AI schedule time if it's in the future + if (aiTime > Date.now()) { + this.guideDateTime = DateTime.fromMillis(aiTime); + } } return false; }); diff --git a/shared/utils.ts b/shared/utils.ts index e2da36cb..1d52b671 100644 --- a/shared/utils.ts +++ b/shared/utils.ts @@ -234,17 +234,6 @@ export function capitalize(s: string): string { return s.charAt(0).toUpperCase() + s.slice(1); } -/** - * Gets the default schedule time for a new schedule. - * Returns current time + 1 hour, rounded to the nearest 10 minutes. - * @returns Time in milliseconds since epoch - */ -export function getDefaultScheduleTime(): number { - const TEN_MINUTES_IN_MS = 10 * 60 * 1000; - const ONE_HOUR_IN_MS = 60 * 60 * 1000; - return Math.ceil((Date.now() + ONE_HOUR_IN_MS) / TEN_MINUTES_IN_MS) * TEN_MINUTES_IN_MS; -} - /** * Computes the differences between two objects and returns the properties