Polish mobile and web experience

This commit is contained in:
2026-08-17 00:18:55 -04:00
parent 6c74436092
commit 9929d7321d
28 changed files with 835 additions and 688 deletions
@@ -10,7 +10,9 @@ import {
import { fetchAuthCapabilities } from "../lib/auth-capabilities";
import { EXPENSE_CATEGORIES as appExpenseCategories } from "../lib/expense-categories";
import { getInvoiceStatus } from "../lib/invoice-status";
import { generateInvoiceNumber as generateMobileInvoiceNumber } from "../lib/invoice-number";
import { formatElapsedSeconds as formatAppElapsedSeconds } from "../lib/time-clock";
import { generateInvoiceNumber as generateWebInvoiceNumber } from "../../web/src/lib/draft-invoice";
import { safeCallbackPath } from "../../web/src/lib/safe-callback-url";
import {
normalizeOptionalId,
@@ -47,6 +49,13 @@ describe("auth contract smoke checks", () => {
});
describe("invoice parity", () => {
test("web and mobile use the device-local date in invoice numbers", () => {
const lateLocalEvening = new Date(2026, 7, 16, 23, 30, 0, 123);
expect(generateMobileInvoiceNumber(lateLocalEvening)).toStartWith("INV-20260816-");
expect(generateWebInvoiceNumber(lateLocalEvening)).toStartWith("INV-20260816-");
});
test("web and mobile agree on draft, paid, sent, and overdue states", () => {
const today = new Date();
today.setHours(0, 0, 0, 0);
+19
View File
@@ -0,0 +1,19 @@
/// <reference types="bun" />
import { describe, expect, test } from "bun:test";
import { resolveActionForeground } from "../lib/action-contrast";
describe("swipe action contrast", () => {
test("uses dark content on bright dark-mode action colors", () => {
expect(resolveActionForeground("#FAFAFA", "#FFFFFF")).toBe("#18181B");
expect(resolveActionForeground("#A1A1AA", "#FFFFFF")).toBe("#18181B");
expect(resolveActionForeground("#4ADE80", "#FFFFFF")).toBe("#18181B");
expect(resolveActionForeground("#FBBF24", "#FFFFFF")).toBe("#18181B");
expect(resolveActionForeground("#F87171", "#FFFFFF")).toBe("#18181B");
});
test("keeps white content on the light-mode primary action", () => {
expect(resolveActionForeground("#18181B", "#FFFFFF")).toBe("#FFFFFF");
});
});