feat(cash-floats): show balance green at or above the limit
The balance was red under the card's limit and plain otherwise. It is now green when the card is set up and at or above its limit, so healthy cards stand out. Cards without an opening balance stay plain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
dda421effa
commit
9c3a6e7f39
2 changed files with 18 additions and 3 deletions
|
|
@ -1,7 +1,7 @@
|
|||
// @vitest-environment jsdom
|
||||
import * as React from "react";
|
||||
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
||||
import { afterEach, beforeEach, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ReactNode } from "react";
|
||||
import type { CashFloatCard } from "@/lib/cash-float-server";
|
||||
|
||||
|
|
@ -108,3 +108,12 @@ it("opens the card's movements from its card number", () => {
|
|||
fireEvent.click(screen.getByRole("button", { name: "Movements for card 3" }));
|
||||
expect(screen.getByText("Movements sheet for 3")).toBeTruthy();
|
||||
});
|
||||
|
||||
describe("balance colour", () => {
|
||||
it("is red under the limit, green at or above it, and plain before set-up", async () => {
|
||||
const { balanceTone } = await import("./cash-floats-view");
|
||||
expect(balanceTone({ low: true, hasOpening: true })).toContain("text-destructive");
|
||||
expect(balanceTone({ low: false, hasOpening: true })).toContain("text-emerald-600");
|
||||
expect(balanceTone({ low: false, hasOpening: false })).toBe("");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ export function CashFloatsView({ cards, users, sites = [] }: { cards: CashFloatC
|
|||
</td>
|
||||
<td className="text-left">{card.holder}</td>
|
||||
<td>{card.assignedOn || "—"}</td>
|
||||
<td className={card.low ? "font-semibold text-destructive" : ""}>{formatCents(card.balance)}</td>
|
||||
<td className={balanceTone(card)}>{formatCents(card.balance)}</td>
|
||||
<td>{formatCents(card.spentSinceTopup)}</td>
|
||||
<td>{formatCents(card.spentThisMonth)}</td>
|
||||
<td>
|
||||
|
|
@ -263,7 +263,7 @@ function CardRow({ card, onOpen, actions }: {
|
|||
<Figure label="This month" value={formatCents(card.spentThisMonth)} />
|
||||
<div className="w-28 shrink-0 text-right">
|
||||
<p className="text-[10px] uppercase tracking-wider text-muted-foreground">Balance</p>
|
||||
<p className={`text-sm font-semibold tabular-nums ${card.low ? "text-destructive" : ""}`}>{formatCents(card.balance)}</p>
|
||||
<p className={`text-sm font-semibold tabular-nums ${balanceTone(card)}`}>{formatCents(card.balance)}</p>
|
||||
</div>
|
||||
<button type="button" aria-expanded={open} aria-label={`Spend per month for card ${card.cardNumber}`} onClick={() => setOpen(o => !o)} className="grid h-9 w-9 shrink-0 place-items-center rounded-md hover:bg-muted">
|
||||
<ChevronRight className={`h-4 w-4 text-muted-foreground transition-transform ${open ? "rotate-90" : ""}`} />
|
||||
|
|
@ -297,3 +297,9 @@ function Figure({ label, value }: { label: string; value: string }) {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/** Red under the limit, green at or above it; a card not set up yet stays plain. */
|
||||
export function balanceTone(card: { low: boolean; hasOpening?: boolean }): string {
|
||||
if (card.low) return "font-semibold text-destructive";
|
||||
return card.hasOpening ? "font-semibold text-emerald-600 dark:text-emerald-400" : "";
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue