Plan UI: support non-standard goal options (#23393)

This commit is contained in:
Michael Geers 2025-09-04 11:21:29 +02:00 • committed by GitHub
parent a561bb45fc
commit 0dee0ebe20
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 87 additions and 5 deletions

View file

@ -225,9 +225,17 @@ export default defineComponent({
},
socOptions() {
// a list of entries from 5 to 100 with a step of 5
return Array.from(Array(20).keys())
const options = Array.from(Array(20).keys())
.map((i) => 5 + i * 5)
.map(this.socOption);
// add current soc value if it's not in the list
if (this.selectedSoc && !options.find((o) => o.value === this.selectedSoc)) {
options.push(this.socOption(this.selectedSoc));
options.sort((a, b) => a.value - b.value);
}
return options;
},
energyOptions() {
const options = energyOptions(
@ -236,7 +244,8 @@ export default defineComponent({
this.fmtWh,
this.fmtPercentage,
"-",
this.socPerKwh
this.socPerKwh,
this.selectedEnergy
);
// remove the first entry (0)
return options.slice(1);

View file

@ -36,11 +36,14 @@ export function energyOptions(
fmtWh: InstanceType<typeof formatter>["fmtWh"],
fmtPercentage: InstanceType<typeof formatter>["fmtPercentage"],
zeroText: string,
socPerKwh?: number
socPerKwh?: number,
selectedValue?: number
) {
const step = optionStep(maxEnergy);
const result = [];
for (let energy = 0; energy <= maxEnergy; energy += step) {
// helper to create option
const makeOption = (energy: number) => {
let text = fmtEnergy(energy, step, fmtWh, zeroText);
const disabled = energy < fromEnergy / 1e3 && energy !== 0;
const soc = estimatedSoc(energy, socPerKwh);
@ -49,7 +52,19 @@ export function energyOptions(
}
// prevent rounding errors
const energyNormal = parseFloat(energy.toFixed(3));
result.push({ energy: energyNormal, text, disabled });
return { energy: energyNormal, text, disabled };
};
// add standard increments
for (let energy = 0; energy <= maxEnergy; energy += step) {
result.push(makeOption(energy));
}
// add selected value if it's not in the list
if (selectedValue && !result.find((o) => o.energy === selectedValue)) {
result.push(makeOption(selectedValue));
result.sort((a, b) => a.energy - b.energy);
}
return result;
}

View file

@ -120,6 +120,35 @@ test.describe("vehicle variations", async () => {
// no repeating plans option
await verifyRepeatingPlanAvailable(page, lp1, false);
});
test("non-standard energy values are visible in dropdown", async ({ page }) => {
await page.goto("/");
const lp1 = await page.getByTestId("loadpoint").first();
// verify guest vehicle
await expect(lp1.getByTestId("vehicle-name")).toHaveText("Guest vehicle");
// create plan with non-standard energy value via API
const response = await page.request.post(
`/api/loadpoints/1/plan/energy/32/2050-09-04T05:00:00.000Z`
);
expect(response.status()).toBe(200);
// verify plan is shown
const plan = await lp1.getByTestId("charging-plan");
await expect(plan).toContainText("32 kWh");
// open modal and verify dropdown
await plan.getByRole("button").click();
const modal = await page.getByTestId("charging-plan-modal").first();
const energySelect = modal.getByTestId("static-plan-energy");
await expect(energySelect).toBeVisible();
// verify non-standard value is selected
await expect(energySelect).toHaveValue("32");
await energySelect.selectOption("70");
await expect(energySelect).toHaveValue("70");
});
});
test.describe("vehicle no soc no capacity", async () => {
@ -212,6 +241,35 @@ test.describe("vehicle variations", async () => {
// repeating plans option
await verifyRepeatingPlanAvailable(page, lp1, true);
});
test("non-standard soc values are visible in dropdown", async ({ page }) => {
await page.goto("/");
const lp1 = await page.getByTestId("loadpoint").first();
await lp1
.getByTestId("change-vehicle")
.locator("select")
.selectOption("Vehicle with SoC with Capacity");
// create plan with non-standard SoC value via API
const response = await page.request.post(
`/api/vehicles/vehicleSocCapacity/plan/soc/72/2050-09-04T05:00:00.000Z`
);
expect(response.status()).toBe(200);
// verify plan is shown
const plan = await lp1.getByTestId("charging-plan");
await expect(plan).toContainText("72%");
// open modal and verify dropdown
plan.getByRole("button").click();
const modal = await page.getByTestId("charging-plan-modal").first();
const socSelect = modal.getByTestId("static-plan-soc");
// verify non-standard value is selected
await expect(socSelect).toHaveValue("72");
await socSelect.selectOption("80%");
await expect(socSelect).toHaveValue("80");
});
});
test.describe("loadpoint with soc, guest vehicle", async () => {