diff --git a/frontend/app/module/input/page/PollingStationPage.tsx b/frontend/app/module/input/page/PollingStationPage.tsx
index b8da00238..82a5643c4 100644
--- a/frontend/app/module/input/page/PollingStationPage.tsx
+++ b/frontend/app/module/input/page/PollingStationPage.tsx
@@ -8,7 +8,7 @@ export function PollingStationPage() {
const targetForm = section || "recount";
- const { register } = useInputMask({});
+ const { register, format } = useInputMask({});
return (
<>
@@ -31,7 +31,7 @@ export function PollingStationPage() {
Is er herteld?
-
+
Aantal kiezers en stemmen
@@ -61,7 +61,7 @@ export function PollingStationPage() {
A |
-
+
|
Stempassen |
@@ -71,7 +71,7 @@ export function PollingStationPage() {
A |
-
+
|
Stempassen |
diff --git a/frontend/lib/ui/inputgrid/InputGrid.tsx b/frontend/lib/ui/inputgrid/InputGrid.tsx
index cb02d6563..4c25e9abb 100644
--- a/frontend/lib/ui/inputgrid/InputGrid.tsx
+++ b/frontend/lib/ui/inputgrid/InputGrid.tsx
@@ -32,11 +32,16 @@ export function InputGrid({ zebra, children }: InputGridProps) {
targetIndex = 0;
}
- inputList.current[activeIndex].el.blur();
- inputList.current[targetIndex].el.focus();
- setTimeout(() => {
- inputList.current[targetIndex].el.select();
- }, 1);
+ const cur = inputList.current[activeIndex];
+ const next = inputList.current[targetIndex];
+
+ if (cur && next) {
+ cur.el.blur();
+ next.el.focus();
+ setTimeout(() => {
+ next.el.select();
+ }, 1);
+ }
}, []);
React.useEffect(() => {
@@ -89,11 +94,9 @@ export function InputGrid({ zebra, children }: InputGridProps) {
});
return () => {
- if (tableEl) {
- tableEl.querySelectorAll("input").forEach((input) => {
- input.removeEventListener("focus", handleFocus);
- });
- }
+ tableEl.querySelectorAll("input").forEach((input) => {
+ input.removeEventListener("focus", handleFocus);
+ });
};
}
}, []);
diff --git a/frontend/lib/ui/inputgrid/inputgrid.module.css b/frontend/lib/ui/inputgrid/inputgrid.module.css
index 0d5875f8b..81c91bb63 100644
--- a/frontend/lib/ui/inputgrid/inputgrid.module.css
+++ b/frontend/lib/ui/inputgrid/inputgrid.module.css
@@ -45,6 +45,7 @@
padding-left: 8px;
padding-right: 8px;
font-style: normal;
+ font-feature-settings: "ss09" on;
}
}
diff --git a/frontend/lib/util/classnames.test.ts b/frontend/lib/util/classnames.test.ts
index 9633bff0b..775df26a2 100644
--- a/frontend/lib/util/classnames.test.ts
+++ b/frontend/lib/util/classnames.test.ts
@@ -1,7 +1,7 @@
import { expect, test } from "vitest";
import { classnames, cn } from "./classnames";
-test("classnames result", async () => {
+test("classnames result", () => {
const result = classnames("test", { test2: true, test3: false });
const result2 = cn("test", { test2: true, test3: false });
expect(result2).toBe(result);
diff --git a/frontend/lib/util/classnames.ts b/frontend/lib/util/classnames.ts
index 8a349b414..1141b6e57 100644
--- a/frontend/lib/util/classnames.ts
+++ b/frontend/lib/util/classnames.ts
@@ -1,4 +1,6 @@
-export function classnames(...args: (string | Record)[]): string {
+export function classnames(
+ ...args: (string | undefined | Record)[]
+): string {
const classes: string[] = [];
for (const arg of args) {
diff --git a/frontend/lib/util/domtoren.test.ts b/frontend/lib/util/domtoren.test.ts
index 16f726fd7..0855c7f6e 100644
--- a/frontend/lib/util/domtoren.test.ts
+++ b/frontend/lib/util/domtoren.test.ts
@@ -1,4 +1,4 @@
-import { expect, test } from "vitest";
+import { expect, test, assert } from "vitest";
import { domtoren } from "./domtoren";
const div = document.createElement("div");
@@ -8,14 +8,15 @@ div.innerHTML = `
`;
-test("domtoren closest", async () => {
+test("domtoren closest", () => {
const aEl = div.querySelector("a");
- const pEl = domtoren(aEl!).closest("p").el();
+ assert(aEl !== null, "aEl is null");
- expect(pEl!.tagName.toLowerCase()).toBe("p");
+ const pEl = domtoren(aEl).closest("p").el();
+ expect(pEl.tagName.toLowerCase()).toBe("p");
});
-test("domtoren toggleClass", async () => {
+test("domtoren toggleClass", () => {
domtoren(div).toggleClass("testclass");
expect(div.classList.contains("testclass")).toBe(true);
});
diff --git a/frontend/lib/util/hook/useInputMask.ts b/frontend/lib/util/hook/useInputMask.ts
index 00c0851f8..90b213eab 100644
--- a/frontend/lib/util/hook/useInputMask.ts
+++ b/frontend/lib/util/hook/useInputMask.ts
@@ -2,39 +2,57 @@ import * as React from "react";
export interface UseInputMaskParams {}
+export type FormatFunc = (s: string | number | null | undefined) => string;
+
export interface UseInputMaskReturn {
+ format: FormatFunc;
register: () => {
onChange: React.ChangeEventHandler;
+ onLoad: React.ChangeEventHandler;
};
}
+const numberFormatter = new Intl.NumberFormat("nl-NL", {
+ maximumFractionDigits: 0
+});
+
export function useInputMask({}: UseInputMaskParams): UseInputMaskReturn {
- const numberFormatter = React.useMemo(() => {
- return new Intl.NumberFormat("nl-NL", {
- maximumFractionDigits: 0
- });
+ const format: FormatFunc = React.useCallback((s) => {
+ if (!s) return "";
+ if (s === "") {
+ return "";
+ }
+
+ let result = `${s}`.replace(/\D/g, "");
+ result = numberFormatter.format(Number(result));
+ return result;
}, []);
const onChange: React.ChangeEventHandler = React.useCallback(
(event) => {
//remove all non numbers
- const value = event.target.value.replace(/\D/g, "");
- if (value !== "") {
- event.target.value = numberFormatter.format(Number(value));
- } else {
- event.target.value = "";
- }
+ event.target.value = format(event.target.value);
+ },
+ [format]
+ );
+
+ const onLoad: React.ChangeEventHandler = React.useCallback(
+ (event) => {
+ console.log("Onload??", event.target.value);
+ event.target.value = format(event.target.value);
},
- [numberFormatter]
+ [format]
);
const register = () => {
return {
- onChange
+ onChange,
+ onLoad
};
};
return {
+ format,
register
};
}