Initial commit: Voiced invoice desktop app

Offline-first invoicing app for Test Vendor, built by Bongbetic.

- Tauri v2 (Rust) + React/TypeScript + IBM Carbon Design System UI
- SQLite (rusqlite) storage with a persistent invoice-number series
- Guided first-run setup, pre-filled vendor/bank details
- Fixed-amount or rate x quantity line items (per sec/min/hour/session/unit)
- GST as CGST+SGST or IGST, Indian amount-in-words
- Optional signature, with a computer-generated note as fallback
- Print-ready PDF export via @react-pdf/renderer
- Windows cross-compile via cargo-xwin (NSIS installer)

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
This commit is contained in:
2026-10-03 23:07:51 +05:30
co-authored by CommandCodeBot
commit 875a12b2e6
121 changed files with 13660 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
const inr = new Intl.NumberFormat("en-IN", {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
/** Indian-grouped number, e.g. 25000 -> "25,000.00" */
export function formatAmount(amount: number): string {
const value = Number.isFinite(amount) ? amount : 0;
return inr.format(value);
}
/** Currency string with the rupee symbol, e.g. "₹25,000.00" */
export function formatCurrency(amount: number, symbol = "₹"): string {
return `${symbol}${formatAmount(amount)}`;
}
/** "2024-06-13" -> "13 Jun 2024" (falls back to the raw value if unparseable). */
export function formatDate(iso: string): string {
if (!iso) return "";
const date = new Date(`${iso}T00:00:00`);
if (Number.isNaN(date.getTime())) return iso;
return date.toLocaleDateString("en-GB", { day: "2-digit", month: "short", year: "numeric" });
}
/** Today as an ISO date (YYYY-MM-DD) in local time. */
export function todayIso(): string {
const now = new Date();
const offset = now.getTimezoneOffset();
return new Date(now.getTime() - offset * 60_000).toISOString().slice(0, 10);
}
/** ISO date `days` from `iso` (defaults to today). */
export function addDays(iso: string, days: number): string {
const base = iso ? new Date(`${iso}T00:00:00`) : new Date();
base.setDate(base.getDate() + (Number.isFinite(days) ? days : 0));
const offset = base.getTimezoneOffset();
return new Date(base.getTime() - offset * 60_000).toISOString().slice(0, 10);
}
export function round2(n: number): number {
return Math.round((Number.isFinite(n) ? n : 0) * 100) / 100;
}