From 0e0d718379e20f1d0dfcde6925f86cd96aff262c Mon Sep 17 00:00:00 2001
From: David Amunga
Date: Thu, 5 Feb 2026 17:21:44 +0300
Subject: [PATCH 1/3] feat: add totalCharges calculation and display in App
component
---
src/App.tsx | 10 ++++++++++
src/services/tabulaService.ts | 34 +++++++++++++++++++++++++---------
src/types/index.ts | 1 +
3 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index 9fa4669..bf1d3ee 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -216,9 +216,12 @@ function App() {
return dateA.getTime() - dateB.getTime();
});
+ const totalCharges = TabulaService.calculateTotalCharges(allTransactions);
+
return {
transactions: allTransactions,
fileName: `Combined_${statements.length}_statements`,
+ totalCharges,
};
};
@@ -541,6 +544,13 @@ function App() {
from {files.length} statement{files.length > 1 ? "s" : ""} •
Choose your export options below
+
+ Total Charges: KES{" "}
+ {(statements[0].totalCharges).toLocaleString("en-US", {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
+
diff --git a/src/services/tabulaService.ts b/src/services/tabulaService.ts
index ab455f4..7bc9d93 100644
--- a/src/services/tabulaService.ts
+++ b/src/services/tabulaService.ts
@@ -10,7 +10,7 @@ export class TabulaService {
*/
static async extractTablesFromPdf(
file: File,
- password?: string
+ password?: string,
): Promise {
const timestamp = Date.now();
const tempInputName = `${FILE_PREFIXES.TEMP_INPUT}${timestamp}.pdf`;
@@ -48,7 +48,7 @@ export class TabulaService {
} catch (error) {
console.warn(
"Failed to clean up temp files during error handling:",
- error
+ error,
);
}
throw new Error(`Tabula extraction failed: ${error.message || error}`);
@@ -63,7 +63,7 @@ export class TabulaService {
const lines = csvContent.split("\n").filter((line) => line.trim());
if (lines.length === 0) {
- return { transactions: [] };
+ return { transactions: [], totalCharges: 0 };
}
let headerIndex = -1;
@@ -80,7 +80,7 @@ export class TabulaService {
}
if (headerIndex === -1) {
- return { transactions: [] };
+ return { transactions: [], totalCharges: 0 };
}
const headerLine = lines[headerIndex].toLowerCase();
@@ -123,15 +123,31 @@ export class TabulaService {
transactions.push(transaction);
}
+ const sortedTransactions = transactions.sort((a, b) => {
+ const dateA = new Date(a.completionTime);
+ const dateB = new Date(b.completionTime);
+ return dateA.getTime() - dateB.getTime();
+ });
+
return {
- transactions: transactions.sort((a, b) => {
- const dateA = new Date(a.completionTime);
- const dateB = new Date(b.completionTime);
- return dateA.getTime() - dateB.getTime();
- }),
+ transactions: sortedTransactions,
+ totalCharges: this.calculateTotalCharges(sortedTransactions),
};
}
+ /**
+ * Calculate total charges using the same logic as chargesSheet.ts
+ */
+ static calculateTotalCharges(transactions: Transaction[]): number {
+ const chargeTransactions = transactions.filter((transaction) =>
+ transaction.details.toLowerCase().includes("charge")
+ );
+
+ return chargeTransactions.reduce((sum, transaction) => {
+ return sum + (transaction.withdrawn || transaction.paidIn || 0);
+ }, 0);
+ }
+
private static parseCSVLine(line: string): string[] {
const fields: string[] = [];
let currentField = "";
diff --git a/src/types/index.ts b/src/types/index.ts
index 6c02523..ea23f7d 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -1,6 +1,7 @@
export interface MPesaStatement {
transactions: Transaction[];
fileName?: string;
+ totalCharges: number;
}
export interface Transaction {
From dd6ea1b3200aed05737467b785c79d9a5e96da9d Mon Sep 17 00:00:00 2001
From: David Amunga
Date: Thu, 5 Feb 2026 17:22:52 +0300
Subject: [PATCH 2/3] feat: update changeset
---
.changeset/public-cloths-tease.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/public-cloths-tease.md
diff --git a/.changeset/public-cloths-tease.md b/.changeset/public-cloths-tease.md
new file mode 100644
index 0000000..5163239
--- /dev/null
+++ b/.changeset/public-cloths-tease.md
@@ -0,0 +1,5 @@
+---
+"mpesa2csv": minor
+---
+
+feat: add total charges in header summary
From c7632d25a1ed63537149253160237d908f50c5c3 Mon Sep 17 00:00:00 2001
From: David Amunga
Date: Thu, 5 Feb 2026 17:25:43 +0300
Subject: [PATCH 3/3] chore: update tailwindcss vite
---
package.json | 2 +-
pnpm-lock.yaml | 314 +++++++++++++++-------------------
src/services/tabulaService.ts | 2 +-
3 files changed, 142 insertions(+), 176 deletions(-)
diff --git a/package.json b/package.json
index 54dc22f..aaa6f11 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-tooltip": "^1.2.8",
- "@tailwindcss/vite": "^4.1.3",
+ "@tailwindcss/vite": "^4.1.18",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-dialog": "^2.2.1",
"@tauri-apps/plugin-fs": "^2.4.2",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index df6075d..445427a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -33,8 +33,8 @@ importers:
specifier: ^1.2.8
version: 1.2.8(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@tailwindcss/vite':
- specifier: ^4.1.3
- version: 4.1.13(vite@7.1.11(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1))
+ specifier: ^4.1.18
+ version: 4.1.18(vite@7.1.11(@types/node@24.5.2)(jiti@2.6.1)(lightningcss@1.30.2))
'@tauri-apps/api':
specifier: ^2
version: 2.8.0
@@ -110,7 +110,7 @@ importers:
version: 19.1.9(@types/react@19.1.13)
'@vitejs/plugin-react':
specifier: ^4.6.0
- version: 4.7.0(vite@7.1.11(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1))
+ version: 4.7.0(vite@7.1.11(@types/node@24.5.2)(jiti@2.6.1)(lightningcss@1.30.2))
source-map-js:
specifier: ^1.2.1
version: 1.2.1
@@ -125,7 +125,7 @@ importers:
version: 5.8.3
vite:
specifier: ^7.0.4
- version: 7.1.11(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)
+ version: 7.1.11(@types/node@24.5.2)(jiti@2.6.1)(lightningcss@1.30.2)
packages:
@@ -463,10 +463,6 @@ packages:
'@types/node':
optional: true
- '@isaacs/fs-minipass@4.0.1':
- resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
- engines: {node: '>=18.0.0'}
-
'@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
@@ -935,65 +931,65 @@ packages:
cpu: [x64]
os: [win32]
- '@tailwindcss/node@4.1.13':
- resolution: {integrity: sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==}
+ '@tailwindcss/node@4.1.18':
+ resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==}
- '@tailwindcss/oxide-android-arm64@4.1.13':
- resolution: {integrity: sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==}
+ '@tailwindcss/oxide-android-arm64@4.1.18':
+ resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [android]
- '@tailwindcss/oxide-darwin-arm64@4.1.13':
- resolution: {integrity: sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==}
+ '@tailwindcss/oxide-darwin-arm64@4.1.18':
+ resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
- '@tailwindcss/oxide-darwin-x64@4.1.13':
- resolution: {integrity: sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==}
+ '@tailwindcss/oxide-darwin-x64@4.1.18':
+ resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@tailwindcss/oxide-freebsd-x64@4.1.13':
- resolution: {integrity: sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==}
+ '@tailwindcss/oxide-freebsd-x64@4.1.18':
+ resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [freebsd]
- '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13':
- resolution: {integrity: sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==}
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18':
+ resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
- '@tailwindcss/oxide-linux-arm64-gnu@4.1.13':
- resolution: {integrity: sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==}
+ '@tailwindcss/oxide-linux-arm64-gnu@4.1.18':
+ resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@tailwindcss/oxide-linux-arm64-musl@4.1.13':
- resolution: {integrity: sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==}
+ '@tailwindcss/oxide-linux-arm64-musl@4.1.18':
+ resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@tailwindcss/oxide-linux-x64-gnu@4.1.13':
- resolution: {integrity: sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==}
+ '@tailwindcss/oxide-linux-x64-gnu@4.1.18':
+ resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@tailwindcss/oxide-linux-x64-musl@4.1.13':
- resolution: {integrity: sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==}
+ '@tailwindcss/oxide-linux-x64-musl@4.1.18':
+ resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@tailwindcss/oxide-wasm32-wasi@4.1.13':
- resolution: {integrity: sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==}
+ '@tailwindcss/oxide-wasm32-wasi@4.1.18':
+ resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
bundledDependencies:
@@ -1004,24 +1000,24 @@ packages:
- '@emnapi/wasi-threads'
- tslib
- '@tailwindcss/oxide-win32-arm64-msvc@4.1.13':
- resolution: {integrity: sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==}
+ '@tailwindcss/oxide-win32-arm64-msvc@4.1.18':
+ resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@tailwindcss/oxide-win32-x64-msvc@4.1.13':
- resolution: {integrity: sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==}
+ '@tailwindcss/oxide-win32-x64-msvc@4.1.18':
+ resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
- '@tailwindcss/oxide@4.1.13':
- resolution: {integrity: sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==}
+ '@tailwindcss/oxide@4.1.18':
+ resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==}
engines: {node: '>= 10'}
- '@tailwindcss/vite@4.1.13':
- resolution: {integrity: sha512-0PmqLQ010N58SbMTJ7BVJ4I2xopiQn/5i6nlb4JmxzQf8zcS5+m2Cv6tqh+sfDwtIdjoEnOvwsGQ1hkUi8QEHQ==}
+ '@tailwindcss/vite@4.1.18':
+ resolution: {integrity: sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==}
peerDependencies:
vite: ^5.2.0 || ^6 || ^7
@@ -1260,10 +1256,6 @@ packages:
chardet@2.1.0:
resolution: {integrity: sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==}
- chownr@3.0.0:
- resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
- engines: {node: '>=18'}
-
ci-info@3.9.0:
resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
engines: {node: '>=8'}
@@ -1502,8 +1494,8 @@ packages:
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
- jiti@2.6.0:
- resolution: {integrity: sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ==}
+ jiti@2.6.1:
+ resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
hasBin: true
js-tokens@4.0.0:
@@ -1540,68 +1532,74 @@ packages:
lie@3.3.0:
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
- lightningcss-darwin-arm64@1.30.1:
- resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==}
+ lightningcss-android-arm64@1.30.2:
+ resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [android]
+
+ lightningcss-darwin-arm64@1.30.2:
+ resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [darwin]
- lightningcss-darwin-x64@1.30.1:
- resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==}
+ lightningcss-darwin-x64@1.30.2:
+ resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [darwin]
- lightningcss-freebsd-x64@1.30.1:
- resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==}
+ lightningcss-freebsd-x64@1.30.2:
+ resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [freebsd]
- lightningcss-linux-arm-gnueabihf@1.30.1:
- resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==}
+ lightningcss-linux-arm-gnueabihf@1.30.2:
+ resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==}
engines: {node: '>= 12.0.0'}
cpu: [arm]
os: [linux]
- lightningcss-linux-arm64-gnu@1.30.1:
- resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==}
+ lightningcss-linux-arm64-gnu@1.30.2:
+ resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
- lightningcss-linux-arm64-musl@1.30.1:
- resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==}
+ lightningcss-linux-arm64-musl@1.30.2:
+ resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
- lightningcss-linux-x64-gnu@1.30.1:
- resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==}
+ lightningcss-linux-x64-gnu@1.30.2:
+ resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
- lightningcss-linux-x64-musl@1.30.1:
- resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==}
+ lightningcss-linux-x64-musl@1.30.2:
+ resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
- lightningcss-win32-arm64-msvc@1.30.1:
- resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==}
+ lightningcss-win32-arm64-msvc@1.30.2:
+ resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [win32]
- lightningcss-win32-x64-msvc@1.30.1:
- resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==}
+ lightningcss-win32-x64-msvc@1.30.2:
+ resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [win32]
- lightningcss@1.30.1:
- resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==}
+ lightningcss@1.30.2:
+ resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
engines: {node: '>= 12.0.0'}
listenercount@1.0.1:
@@ -1662,8 +1660,8 @@ packages:
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
- magic-string@0.30.19:
- resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==}
+ magic-string@0.30.21:
+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
@@ -1683,14 +1681,6 @@ packages:
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
- minipass@7.1.2:
- resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
- engines: {node: '>=16 || 14 >=14.17'}
-
- minizlib@3.1.0:
- resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
- engines: {node: '>= 18'}
-
mkdirp@0.5.6:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
hasBin: true
@@ -1955,6 +1945,9 @@ packages:
tailwindcss@4.1.13:
resolution: {integrity: sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==}
+ tailwindcss@4.1.18:
+ resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==}
+
tapable@2.2.3:
resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==}
engines: {node: '>=6'}
@@ -1963,10 +1956,6 @@ packages:
resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
engines: {node: '>=6'}
- tar@7.5.6:
- resolution: {integrity: sha512-xqUeu2JAIJpXyvskvU3uvQW8PAmHrtXp2KDuMJwQqW8Sqq0CaZBAQ+dKS3RBXVhU4wC5NjAdKrmh84241gO9cA==}
- engines: {node: '>=18'}
-
tauri-plugin-pldownloader-api@1.0.1:
resolution: {integrity: sha512-t7gXkHPkozEHJLJh21RGQOem0US0kiFqEhE+8ugvCcI4Mk60IF1e8hJoADWyUZp/J3jR+HHM4WBP/H1tcjfJvw==}
@@ -2106,10 +2095,6 @@ packages:
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
- yallist@5.0.0:
- resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
- engines: {node: '>=18'}
-
zip-stream@4.1.1:
resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==}
engines: {node: '>= 10'}
@@ -2528,10 +2513,6 @@ snapshots:
optionalDependencies:
'@types/node': 24.5.2
- '@isaacs/fs-minipass@4.0.1':
- dependencies:
- minipass: 7.1.2
-
'@jridgewell/gen-mapping@0.3.13':
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
@@ -2939,76 +2920,73 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.52.0':
optional: true
- '@tailwindcss/node@4.1.13':
+ '@tailwindcss/node@4.1.18':
dependencies:
'@jridgewell/remapping': 2.3.5
enhanced-resolve: 5.18.3
- jiti: 2.6.0
- lightningcss: 1.30.1
- magic-string: 0.30.19
+ jiti: 2.6.1
+ lightningcss: 1.30.2
+ magic-string: 0.30.21
source-map-js: 1.2.1
- tailwindcss: 4.1.13
+ tailwindcss: 4.1.18
- '@tailwindcss/oxide-android-arm64@4.1.13':
+ '@tailwindcss/oxide-android-arm64@4.1.18':
optional: true
- '@tailwindcss/oxide-darwin-arm64@4.1.13':
+ '@tailwindcss/oxide-darwin-arm64@4.1.18':
optional: true
- '@tailwindcss/oxide-darwin-x64@4.1.13':
+ '@tailwindcss/oxide-darwin-x64@4.1.18':
optional: true
- '@tailwindcss/oxide-freebsd-x64@4.1.13':
+ '@tailwindcss/oxide-freebsd-x64@4.1.18':
optional: true
- '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13':
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18':
optional: true
- '@tailwindcss/oxide-linux-arm64-gnu@4.1.13':
+ '@tailwindcss/oxide-linux-arm64-gnu@4.1.18':
optional: true
- '@tailwindcss/oxide-linux-arm64-musl@4.1.13':
+ '@tailwindcss/oxide-linux-arm64-musl@4.1.18':
optional: true
- '@tailwindcss/oxide-linux-x64-gnu@4.1.13':
+ '@tailwindcss/oxide-linux-x64-gnu@4.1.18':
optional: true
- '@tailwindcss/oxide-linux-x64-musl@4.1.13':
+ '@tailwindcss/oxide-linux-x64-musl@4.1.18':
optional: true
- '@tailwindcss/oxide-wasm32-wasi@4.1.13':
+ '@tailwindcss/oxide-wasm32-wasi@4.1.18':
optional: true
- '@tailwindcss/oxide-win32-arm64-msvc@4.1.13':
+ '@tailwindcss/oxide-win32-arm64-msvc@4.1.18':
optional: true
- '@tailwindcss/oxide-win32-x64-msvc@4.1.13':
+ '@tailwindcss/oxide-win32-x64-msvc@4.1.18':
optional: true
- '@tailwindcss/oxide@4.1.13':
- dependencies:
- detect-libc: 2.1.0
- tar: 7.5.6
+ '@tailwindcss/oxide@4.1.18':
optionalDependencies:
- '@tailwindcss/oxide-android-arm64': 4.1.13
- '@tailwindcss/oxide-darwin-arm64': 4.1.13
- '@tailwindcss/oxide-darwin-x64': 4.1.13
- '@tailwindcss/oxide-freebsd-x64': 4.1.13
- '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.13
- '@tailwindcss/oxide-linux-arm64-gnu': 4.1.13
- '@tailwindcss/oxide-linux-arm64-musl': 4.1.13
- '@tailwindcss/oxide-linux-x64-gnu': 4.1.13
- '@tailwindcss/oxide-linux-x64-musl': 4.1.13
- '@tailwindcss/oxide-wasm32-wasi': 4.1.13
- '@tailwindcss/oxide-win32-arm64-msvc': 4.1.13
- '@tailwindcss/oxide-win32-x64-msvc': 4.1.13
-
- '@tailwindcss/vite@4.1.13(vite@7.1.11(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1))':
- dependencies:
- '@tailwindcss/node': 4.1.13
- '@tailwindcss/oxide': 4.1.13
- tailwindcss: 4.1.13
- vite: 7.1.11(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)
+ '@tailwindcss/oxide-android-arm64': 4.1.18
+ '@tailwindcss/oxide-darwin-arm64': 4.1.18
+ '@tailwindcss/oxide-darwin-x64': 4.1.18
+ '@tailwindcss/oxide-freebsd-x64': 4.1.18
+ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18
+ '@tailwindcss/oxide-linux-arm64-gnu': 4.1.18
+ '@tailwindcss/oxide-linux-arm64-musl': 4.1.18
+ '@tailwindcss/oxide-linux-x64-gnu': 4.1.18
+ '@tailwindcss/oxide-linux-x64-musl': 4.1.18
+ '@tailwindcss/oxide-wasm32-wasi': 4.1.18
+ '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18
+ '@tailwindcss/oxide-win32-x64-msvc': 4.1.18
+
+ '@tailwindcss/vite@4.1.18(vite@7.1.11(@types/node@24.5.2)(jiti@2.6.1)(lightningcss@1.30.2))':
+ dependencies:
+ '@tailwindcss/node': 4.1.18
+ '@tailwindcss/oxide': 4.1.18
+ tailwindcss: 4.1.18
+ vite: 7.1.11(@types/node@24.5.2)(jiti@2.6.1)(lightningcss@1.30.2)
'@tauri-apps/api@2.8.0': {}
@@ -3126,7 +3104,7 @@ snapshots:
dependencies:
csstype: 3.1.3
- '@vitejs/plugin-react@4.7.0(vite@7.1.11(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1))':
+ '@vitejs/plugin-react@4.7.0(vite@7.1.11(@types/node@24.5.2)(jiti@2.6.1)(lightningcss@1.30.2))':
dependencies:
'@babel/core': 7.28.4
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4)
@@ -3134,7 +3112,7 @@ snapshots:
'@rolldown/pluginutils': 1.0.0-beta.27
'@types/babel__core': 7.20.5
react-refresh: 0.17.0
- vite: 7.1.11(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)
+ vite: 7.1.11(@types/node@24.5.2)(jiti@2.6.1)(lightningcss@1.30.2)
transitivePeerDependencies:
- supports-color
@@ -3257,8 +3235,6 @@ snapshots:
chardet@2.1.0: {}
- chownr@3.0.0: {}
-
ci-info@3.9.0: {}
class-variance-authority@0.7.1:
@@ -3503,7 +3479,7 @@ snapshots:
isexe@2.0.0: {}
- jiti@2.6.0: {}
+ jiti@2.6.1: {}
js-tokens@4.0.0: {}
@@ -3539,50 +3515,54 @@ snapshots:
dependencies:
immediate: 3.0.6
- lightningcss-darwin-arm64@1.30.1:
+ lightningcss-android-arm64@1.30.2:
+ optional: true
+
+ lightningcss-darwin-arm64@1.30.2:
optional: true
- lightningcss-darwin-x64@1.30.1:
+ lightningcss-darwin-x64@1.30.2:
optional: true
- lightningcss-freebsd-x64@1.30.1:
+ lightningcss-freebsd-x64@1.30.2:
optional: true
- lightningcss-linux-arm-gnueabihf@1.30.1:
+ lightningcss-linux-arm-gnueabihf@1.30.2:
optional: true
- lightningcss-linux-arm64-gnu@1.30.1:
+ lightningcss-linux-arm64-gnu@1.30.2:
optional: true
- lightningcss-linux-arm64-musl@1.30.1:
+ lightningcss-linux-arm64-musl@1.30.2:
optional: true
- lightningcss-linux-x64-gnu@1.30.1:
+ lightningcss-linux-x64-gnu@1.30.2:
optional: true
- lightningcss-linux-x64-musl@1.30.1:
+ lightningcss-linux-x64-musl@1.30.2:
optional: true
- lightningcss-win32-arm64-msvc@1.30.1:
+ lightningcss-win32-arm64-msvc@1.30.2:
optional: true
- lightningcss-win32-x64-msvc@1.30.1:
+ lightningcss-win32-x64-msvc@1.30.2:
optional: true
- lightningcss@1.30.1:
+ lightningcss@1.30.2:
dependencies:
detect-libc: 2.1.0
optionalDependencies:
- lightningcss-darwin-arm64: 1.30.1
- lightningcss-darwin-x64: 1.30.1
- lightningcss-freebsd-x64: 1.30.1
- lightningcss-linux-arm-gnueabihf: 1.30.1
- lightningcss-linux-arm64-gnu: 1.30.1
- lightningcss-linux-arm64-musl: 1.30.1
- lightningcss-linux-x64-gnu: 1.30.1
- lightningcss-linux-x64-musl: 1.30.1
- lightningcss-win32-arm64-msvc: 1.30.1
- lightningcss-win32-x64-msvc: 1.30.1
+ lightningcss-android-arm64: 1.30.2
+ lightningcss-darwin-arm64: 1.30.2
+ lightningcss-darwin-x64: 1.30.2
+ lightningcss-freebsd-x64: 1.30.2
+ lightningcss-linux-arm-gnueabihf: 1.30.2
+ lightningcss-linux-arm64-gnu: 1.30.2
+ lightningcss-linux-arm64-musl: 1.30.2
+ lightningcss-linux-x64-gnu: 1.30.2
+ lightningcss-linux-x64-musl: 1.30.2
+ lightningcss-win32-arm64-msvc: 1.30.2
+ lightningcss-win32-x64-msvc: 1.30.2
listenercount@1.0.1: {}
@@ -3626,7 +3606,7 @@ snapshots:
dependencies:
react: 19.1.1
- magic-string@0.30.19:
+ magic-string@0.30.21:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
@@ -3647,12 +3627,6 @@ snapshots:
minimist@1.2.8: {}
- minipass@7.1.2: {}
-
- minizlib@3.1.0:
- dependencies:
- minipass: 7.1.2
-
mkdirp@0.5.6:
dependencies:
minimist: 1.2.8
@@ -3885,6 +3859,8 @@ snapshots:
tailwindcss@4.1.13: {}
+ tailwindcss@4.1.18: {}
+
tapable@2.2.3: {}
tar-stream@2.2.0:
@@ -3895,14 +3871,6 @@ snapshots:
inherits: 2.0.4
readable-stream: 3.6.2
- tar@7.5.6:
- dependencies:
- '@isaacs/fs-minipass': 4.0.1
- chownr: 3.0.0
- minipass: 7.1.2
- minizlib: 3.1.0
- yallist: 5.0.0
-
tauri-plugin-pldownloader-api@1.0.1:
dependencies:
'@tauri-apps/api': 2.8.0
@@ -3972,7 +3940,7 @@ snapshots:
uuid@8.3.2: {}
- vite@7.1.11(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1):
+ vite@7.1.11(@types/node@24.5.2)(jiti@2.6.1)(lightningcss@1.30.2):
dependencies:
esbuild: 0.25.10
fdir: 6.5.0(picomatch@4.0.3)
@@ -3983,8 +3951,8 @@ snapshots:
optionalDependencies:
'@types/node': 24.5.2
fsevents: 2.3.3
- jiti: 2.6.0
- lightningcss: 1.30.1
+ jiti: 2.6.1
+ lightningcss: 1.30.2
webidl-conversions@3.0.1: {}
@@ -4003,8 +3971,6 @@ snapshots:
yallist@3.1.1: {}
- yallist@5.0.0: {}
-
zip-stream@4.1.1:
dependencies:
archiver-utils: 3.0.4
diff --git a/src/services/tabulaService.ts b/src/services/tabulaService.ts
index 7bc9d93..ff6a397 100644
--- a/src/services/tabulaService.ts
+++ b/src/services/tabulaService.ts
@@ -140,7 +140,7 @@ export class TabulaService {
*/
static calculateTotalCharges(transactions: Transaction[]): number {
const chargeTransactions = transactions.filter((transaction) =>
- transaction.details.toLowerCase().includes("charge")
+ transaction.details.toLowerCase().includes("charge"),
);
return chargeTransactions.reduce((sum, transaction) => {