Press-and-hold spinner buttons repeat by 1000; floor compound interest growth (securities and real estate) and pension lump sum to nearest 1000 throughout
Deploy App / deploy (push) Successful in 43s
Deploy App / deploy (push) Successful in 43s
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { InfoBubble } from "@/components/InfoBubble";
|
||||
import { floorToThousand, formatChf, parseChfInput } from "@/lib/format";
|
||||
|
||||
@@ -64,11 +64,39 @@ export function MoneyInput({
|
||||
}) {
|
||||
const [focused, setFocused] = useState(false);
|
||||
const [text, setText] = useState(() => String(Math.floor(value || 0)));
|
||||
const valueRef = useRef(value);
|
||||
useEffect(() => {
|
||||
valueRef.current = value;
|
||||
}, [value]);
|
||||
const holdTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const holdInterval = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
|
||||
function step(delta: number) {
|
||||
onChange(floorToThousand(value) + delta);
|
||||
onChange(floorToThousand(valueRef.current) + delta);
|
||||
}
|
||||
|
||||
function stopHold() {
|
||||
if (holdTimeout.current) {
|
||||
clearTimeout(holdTimeout.current);
|
||||
holdTimeout.current = null;
|
||||
}
|
||||
if (holdInterval.current) {
|
||||
clearInterval(holdInterval.current);
|
||||
holdInterval.current = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Klick-und-Halten: sofortiger erster Schritt, nach kurzer Verzoegerung
|
||||
// fortlaufende Wiederholung, bis losgelassen wird.
|
||||
function startHold(delta: number) {
|
||||
step(delta);
|
||||
holdTimeout.current = setTimeout(() => {
|
||||
holdInterval.current = setInterval(() => step(delta), 100);
|
||||
}, 400);
|
||||
}
|
||||
|
||||
useEffect(() => stopHold, []);
|
||||
|
||||
return (
|
||||
<div className={`relative ${className ?? "w-full"}`}>
|
||||
<input
|
||||
@@ -91,8 +119,17 @@ export function MoneyInput({
|
||||
type="button"
|
||||
tabIndex={-1}
|
||||
aria-label="Um 1'000 erhoehen"
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
onClick={() => step(1000)}
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault();
|
||||
startHold(1000);
|
||||
}}
|
||||
onMouseUp={stopHold}
|
||||
onMouseLeave={stopHold}
|
||||
onTouchStart={(e) => {
|
||||
e.preventDefault();
|
||||
startHold(1000);
|
||||
}}
|
||||
onTouchEnd={stopHold}
|
||||
className="flex flex-1 items-center justify-center text-[8px] leading-none text-zinc-500 hover:bg-zinc-100 dark:text-zinc-400 dark:hover:bg-zinc-800"
|
||||
>
|
||||
▲
|
||||
@@ -101,8 +138,17 @@ export function MoneyInput({
|
||||
type="button"
|
||||
tabIndex={-1}
|
||||
aria-label="Um 1'000 verringern"
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
onClick={() => step(-1000)}
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault();
|
||||
startHold(-1000);
|
||||
}}
|
||||
onMouseUp={stopHold}
|
||||
onMouseLeave={stopHold}
|
||||
onTouchStart={(e) => {
|
||||
e.preventDefault();
|
||||
startHold(-1000);
|
||||
}}
|
||||
onTouchEnd={stopHold}
|
||||
className="flex flex-1 items-center justify-center border-t border-zinc-300 text-[8px] leading-none text-zinc-500 hover:bg-zinc-100 dark:border-zinc-600 dark:text-zinc-400 dark:hover:bg-zinc-800"
|
||||
>
|
||||
▼
|
||||
|
||||
Reference in New Issue
Block a user