From 34d3554f7236accab1289a1f18df6de086bda493 Mon Sep 17 00:00:00 2001 From: vladtechno Date: Thu, 18 Jun 2026 19:13:16 +1000 Subject: [PATCH] feat(driver-pwa): pure money/phone/amount helpers + tests Co-Authored-By: claude-flow --- driver-pwa/frontend/src/lib/amount.test.ts | 19 +++++++++++++++++++ driver-pwa/frontend/src/lib/amount.ts | 16 ++++++++++++++++ driver-pwa/frontend/src/lib/format.test.ts | 17 +++++++++++++++++ driver-pwa/frontend/src/lib/format.ts | 21 +++++++++++++++++++++ 4 files changed, 73 insertions(+) create mode 100644 driver-pwa/frontend/src/lib/amount.test.ts create mode 100644 driver-pwa/frontend/src/lib/amount.ts create mode 100644 driver-pwa/frontend/src/lib/format.test.ts create mode 100644 driver-pwa/frontend/src/lib/format.ts diff --git a/driver-pwa/frontend/src/lib/amount.test.ts b/driver-pwa/frontend/src/lib/amount.test.ts new file mode 100644 index 0000000..7370485 --- /dev/null +++ b/driver-pwa/frontend/src/lib/amount.test.ts @@ -0,0 +1,19 @@ +import { describe, it, expect } from "vitest"; +import { keypadReduce, withCommission } from "./amount"; + +describe("amount keypad", () => { + it("appends digits, ignores leading zero, caps length", () => { + expect(keypadReduce("0", "5")).toBe("5"); + expect(keypadReduce("100", "0")).toBe("1000"); + expect(keypadReduce("", "0")).toBe(""); + expect(keypadReduce("999999", "9")).toBe("999999"); + }); + it("backspace removes last digit", () => { + expect(keypadReduce("105", "back")).toBe("10"); + expect(keypadReduce("", "back")).toBe(""); + }); + it("withCommission computes total at given rate", () => { + expect(withCommission(1000, 0.052)).toEqual({ commission: 52, total: 1052 }); + expect(withCommission(333, 0.052)).toEqual({ commission: 17.32, total: 350.32 }); + }); +}); diff --git a/driver-pwa/frontend/src/lib/amount.ts b/driver-pwa/frontend/src/lib/amount.ts new file mode 100644 index 0000000..deb7e9f --- /dev/null +++ b/driver-pwa/frontend/src/lib/amount.ts @@ -0,0 +1,16 @@ +const MAX_DIGITS = 6; + +export function keypadReduce(current: string, key: string): string { + if (key === "back") return current.slice(0, -1); + if (!/^\d$/.test(key)) return current; + if (current === "0") return key === "0" ? "0" : key; // replace leading zero + if (current === "" && key === "0") return ""; // no leading zero from empty + if (current.length >= MAX_DIGITS) return current; + return current + key; +} + +export function withCommission(base: number, rate: number): { commission: number; total: number } { + const commission = Math.round(base * rate * 100) / 100; + const total = Math.round((base + commission) * 100) / 100; + return { commission, total }; +} diff --git a/driver-pwa/frontend/src/lib/format.test.ts b/driver-pwa/frontend/src/lib/format.test.ts new file mode 100644 index 0000000..8c60206 --- /dev/null +++ b/driver-pwa/frontend/src/lib/format.test.ts @@ -0,0 +1,17 @@ +import { describe, it, expect } from "vitest"; +import { formatMoney, formatPhone, digitsOnly } from "./format"; + +describe("format", () => { + it("formatMoney groups thousands and adds ₽", () => { + expect(formatMoney(1000)).toBe("1 000 ₽"); + expect(formatMoney(-3200)).toBe("−3 200 ₽"); + expect(formatMoney(0)).toBe("0 ₽"); + }); + it("digitsOnly strips non-digits", () => { + expect(digitsOnly("+7 (914) 305-44-00")).toBe("79143054400"); + }); + it("formatPhone renders +7 mask progressively", () => { + expect(formatPhone("9143054400")).toBe("+7 914 305-44-00"); + expect(formatPhone("914305")).toBe("+7 914 305"); + }); +}); diff --git a/driver-pwa/frontend/src/lib/format.ts b/driver-pwa/frontend/src/lib/format.ts new file mode 100644 index 0000000..730e394 --- /dev/null +++ b/driver-pwa/frontend/src/lib/format.ts @@ -0,0 +1,21 @@ +export function digitsOnly(s: string): string { + return (s || "").replace(/\D/g, ""); +} + +export function formatMoney(rub: number): string { + const neg = rub < 0; + const abs = Math.abs(Math.round(rub)); + const grouped = abs.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " "); + return `${neg ? "−" : ""}${grouped} ₽`; +} + +/** Render a Russian mobile from up-to-10 national digits as +7 914 305-44-00. */ +export function formatPhone(national10: string): string { + const d = digitsOnly(national10).slice(0, 10); + const p: string[] = ["+7"]; + if (d.length > 0) p.push(" " + d.slice(0, 3)); + if (d.length > 3) p.push(" " + d.slice(3, 6)); + if (d.length > 6) p.push("-" + d.slice(6, 8)); + if (d.length > 8) p.push("-" + d.slice(8, 10)); + return p.join(""); +}