Compare commits

...

5 Commits

Author SHA1 Message Date
Elisiário Couto
fa7281af06 fix(frontend): Add index signature to PieDataPoint interface.
Resolves TypeScript error where PieDataPoint[] was not assignable to
ChartDataInput[] by adding the required string index signature.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-16 18:29:04 +01:00
Elisiário Couto
1c433587ba refactor(frontend): Replace LoadingSpinner with shadcn skeleton components.
- Created AccountsSkeleton.tsx and NotificationsSkeleton.tsx components
- Updated AccountsOverview.tsx and Notifications.tsx to use skeletons
- Removed unused LoadingSpinner.tsx component
- Improved loading state UX by showing content structure

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-16 18:23:50 +01:00
copilot-swe-agent[bot]
93137f9998 fix(frontend): Resolve linting issue in skeleton component
Co-authored-by: elisiariocouto <818914+elisiariocouto@users.noreply.github.com>
2025-09-15 23:34:36 +00:00
copilot-swe-agent[bot]
9e68810239 feat(frontend): Complete shadcn migration of skeleton and styling components
Co-authored-by: elisiariocouto <818914+elisiariocouto@users.noreply.github.com>
2025-09-15 23:31:51 +00:00
copilot-swe-agent[bot]
54e4c5b43c Initial plan 2025-09-15 23:23:14 +00:00
19 changed files with 763 additions and 373 deletions

View File

@@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-progress": "^1.1.7",
"@radix-ui/react-select": "^2.2.6", "@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-slot": "^1.2.3",
"@tailwindcss/forms": "^0.5.10", "@tailwindcss/forms": "^0.5.10",
@@ -29,6 +30,7 @@
"react-day-picker": "^9.10.0", "react-day-picker": "^9.10.0",
"react-dom": "^19.1.1", "react-dom": "^19.1.1",
"recharts": "^3.2.0", "recharts": "^3.2.0",
"sonner": "^2.0.7",
"tailwind-merge": "^3.3.1", "tailwind-merge": "^3.3.1",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"tailwindcss-animate": "^1.0.7" "tailwindcss-animate": "^1.0.7"
@@ -1637,6 +1639,30 @@
} }
} }
}, },
"node_modules/@radix-ui/react-progress": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz",
"integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-context": "1.1.2",
"@radix-ui/react-primitive": "2.1.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-select": { "node_modules/@radix-ui/react-select": {
"version": "2.2.6", "version": "2.2.6",
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz",
@@ -1897,9 +1923,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.2.tgz",
"integrity": "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag==", "integrity": "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -1911,9 +1937,9 @@
] ]
}, },
"node_modules/@rollup/rollup-android-arm64": { "node_modules/@rollup/rollup-android-arm64": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.2.tgz",
"integrity": "sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw==", "integrity": "sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1925,9 +1951,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-arm64": { "node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.2.tgz",
"integrity": "sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw==", "integrity": "sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1939,9 +1965,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-x64": { "node_modules/@rollup/rollup-darwin-x64": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.2.tgz",
"integrity": "sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw==", "integrity": "sha512-Wa/Wn8RFkIkr1vy1k1PB//VYhLnlnn5eaJkfTQKivirOvzu5uVd2It01ukeQstMursuz7S1bU+8WW+1UPXpa8A==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1953,9 +1979,9 @@
] ]
}, },
"node_modules/@rollup/rollup-freebsd-arm64": { "node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.2.tgz",
"integrity": "sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA==", "integrity": "sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1967,9 +1993,9 @@
] ]
}, },
"node_modules/@rollup/rollup-freebsd-x64": { "node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.2.tgz",
"integrity": "sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ==", "integrity": "sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1981,9 +2007,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-gnueabihf": { "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.2.tgz",
"integrity": "sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg==", "integrity": "sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -1995,9 +2021,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-musleabihf": { "node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.2.tgz",
"integrity": "sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw==", "integrity": "sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -2009,9 +2035,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-gnu": { "node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.2.tgz",
"integrity": "sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw==", "integrity": "sha512-df0Eou14ojtUdLQdPFnymEQteENwSJAdLf5KCDrmZNsy1c3YaCNaJvYsEUHnrg+/DLBH612/R0xd3dD03uz2dg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2023,9 +2049,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-musl": { "node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.2.tgz",
"integrity": "sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w==", "integrity": "sha512-iPeouV0UIDtz8j1YFR4OJ/zf7evjauqv7jQ/EFs0ClIyL+by++hiaDAfFipjOgyz6y6xbDvJuiU4HwpVMpRFDQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2036,10 +2062,10 @@
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-loongarch64-gnu": { "node_modules/@rollup/rollup-linux-loong64-gnu": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.50.2.tgz",
"integrity": "sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q==", "integrity": "sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw==",
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
@@ -2051,9 +2077,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-ppc64-gnu": { "node_modules/@rollup/rollup-linux-ppc64-gnu": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.2.tgz",
"integrity": "sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q==", "integrity": "sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@@ -2065,9 +2091,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-riscv64-gnu": { "node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.2.tgz",
"integrity": "sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ==", "integrity": "sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@@ -2079,9 +2105,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-riscv64-musl": { "node_modules/@rollup/rollup-linux-riscv64-musl": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.2.tgz",
"integrity": "sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg==", "integrity": "sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@@ -2093,9 +2119,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-s390x-gnu": { "node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.2.tgz",
"integrity": "sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg==", "integrity": "sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
@@ -2107,9 +2133,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-gnu": { "node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.2.tgz",
"integrity": "sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA==", "integrity": "sha512-9Jie/At6qk70dNIcopcL4p+1UirusEtznpNtcq/u/C5cC4HBX7qSGsYIcG6bdxj15EYWhHiu02YvmdPzylIZlA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -2121,9 +2147,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-musl": { "node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.2.tgz",
"integrity": "sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg==", "integrity": "sha512-HPNJwxPL3EmhzeAnsWQCM3DcoqOz3/IC6de9rWfGR8ZCuEHETi9km66bH/wG3YH0V3nyzyFEGUZeL5PKyy4xvw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -2135,9 +2161,9 @@
] ]
}, },
"node_modules/@rollup/rollup-openharmony-arm64": { "node_modules/@rollup/rollup-openharmony-arm64": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.2.tgz",
"integrity": "sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA==", "integrity": "sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2149,9 +2175,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-arm64-msvc": { "node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.2.tgz",
"integrity": "sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ==", "integrity": "sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -2163,9 +2189,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-ia32-msvc": { "node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.2.tgz",
"integrity": "sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A==", "integrity": "sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -2177,9 +2203,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-x64-msvc": { "node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.2.tgz",
"integrity": "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA==", "integrity": "sha512-APwKy6YUhvZaEoHyM+9xqmTpviEI+9eL7LoCH+aLcvWYHJ663qG5zx7WzWZY+a9qkg5JtzcMyJ9z0WtQBMDmgA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -2228,9 +2254,9 @@
} }
}, },
"node_modules/@tanstack/query-core": { "node_modules/@tanstack/query-core": {
"version": "5.87.4", "version": "5.89.0",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.87.4.tgz", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.89.0.tgz",
"integrity": "sha512-uNsg6zMxraEPDVO2Bn+F3/ctHi+Zsk+MMpcN8h6P7ozqD088F6mFY5TfGM7zuyIrL7HKpDyu6QHfLWiDxh3cuw==", "integrity": "sha512-joFV1MuPhSLsKfTzwjmPDrp8ENfZ9N23ymFu07nLfn3JCkSHy0CFgsyhHTJOmWaumC/WiNIKM0EJyduCF/Ih/Q==",
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"type": "github", "type": "github",
@@ -2238,12 +2264,12 @@
} }
}, },
"node_modules/@tanstack/react-query": { "node_modules/@tanstack/react-query": {
"version": "5.87.4", "version": "5.89.0",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.87.4.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.89.0.tgz",
"integrity": "sha512-T5GT/1ZaNsUXf5I3RhcYuT17I4CPlbZgyLxc/ZGv7ciS6esytlbjb3DgUFO6c8JWYMDpdjSWInyGZUErgzqhcA==", "integrity": "sha512-SXbtWSTSRXyBOe80mszPxpEbaN4XPRUp/i0EfQK1uyj3KCk/c8FuPJNIRwzOVe/OU3rzxrYtiNabsAmk1l714A==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tanstack/query-core": "5.87.4" "@tanstack/query-core": "5.89.0"
}, },
"funding": { "funding": {
"type": "github", "type": "github",
@@ -2254,14 +2280,14 @@
} }
}, },
"node_modules/@tanstack/react-router": { "node_modules/@tanstack/react-router": {
"version": "1.131.41", "version": "1.131.44",
"resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.131.41.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.131.44.tgz",
"integrity": "sha512-QEbTYpAosiD8e4qEZRr9aJipGSb8pQc+pfZwK6NCD2Tcxwu2oF6MVtwv0bIDLRpZP0VJMBpxXlTRISUDNMNqIA==", "integrity": "sha512-LREJfrl8lSedXHCRAAt0HvnHFP9ikAQWnVhYRM++B26w4ZYQBbLvgCT1BCDZVY7MR6rslcd4OfgpZMOyVhNzFg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tanstack/history": "1.131.2", "@tanstack/history": "1.131.2",
"@tanstack/react-store": "^0.7.0", "@tanstack/react-store": "^0.7.0",
"@tanstack/router-core": "1.131.41", "@tanstack/router-core": "1.131.44",
"isbot": "^5.1.22", "isbot": "^5.1.22",
"tiny-invariant": "^1.3.3", "tiny-invariant": "^1.3.3",
"tiny-warning": "^1.0.3" "tiny-warning": "^1.0.3"
@@ -2317,12 +2343,12 @@
} }
}, },
"node_modules/@tanstack/router-cli": { "node_modules/@tanstack/router-cli": {
"version": "1.131.41", "version": "1.131.44",
"resolved": "https://registry.npmjs.org/@tanstack/router-cli/-/router-cli-1.131.41.tgz", "resolved": "https://registry.npmjs.org/@tanstack/router-cli/-/router-cli-1.131.44.tgz",
"integrity": "sha512-EpLnnCwwCd94HRCWHoa1GZGtIWIffx4rPBb6gbWm4cvyEIGV2Gq+27vL2OEw819/elxyBQmG2RrPB8+7dfVACw==", "integrity": "sha512-fKt2Whxbi3mvLXxVphSqlvVQyKe6BjdmOj5n+9LOgXQnFGyRwxrFR5cnNF+N4gUGp9iwnJpguZHXH4rNF5Xc+A==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tanstack/router-generator": "1.131.41", "@tanstack/router-generator": "1.131.44",
"chokidar": "^3.6.0", "chokidar": "^3.6.0",
"yargs": "^17.7.2" "yargs": "^17.7.2"
}, },
@@ -2338,9 +2364,9 @@
} }
}, },
"node_modules/@tanstack/router-core": { "node_modules/@tanstack/router-core": {
"version": "1.131.41", "version": "1.131.44",
"resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.131.41.tgz", "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.131.44.tgz",
"integrity": "sha512-VoLly00DWM0abKuVPRm8wiwGtRBHOKs6K896fy48Q/KYoDVLs8kRCRjFGS7rGnYC2FIkmmvHqYRqNg7jgCx2yg==", "integrity": "sha512-Npi9xB3GSYZhRW8+gPhP6bEbyx0vNc8ZNwsi0JapdiFpIiszgRJ57pesy/rklruv46gYQjLVA5KDOsuaCT/urA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tanstack/history": "1.131.2", "@tanstack/history": "1.131.2",
@@ -2360,12 +2386,12 @@
} }
}, },
"node_modules/@tanstack/router-generator": { "node_modules/@tanstack/router-generator": {
"version": "1.131.41", "version": "1.131.44",
"resolved": "https://registry.npmjs.org/@tanstack/router-generator/-/router-generator-1.131.41.tgz", "resolved": "https://registry.npmjs.org/@tanstack/router-generator/-/router-generator-1.131.44.tgz",
"integrity": "sha512-HsDkBU1u/KvHrzn76v/9oeyMFuxvVlE3dfIu4fldZbPy/i903DWBwODIDGe6fVUsYtzPPrRvNtbjV18HVz5GCA==", "integrity": "sha512-CnrlRkGatdQXdvTteflOTMANupb1z59CO3DSV+UzBkTG+g+vfWgJeKQ0EkfwZ2QuS6Su2v5r5EMHs/AookeZZw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tanstack/router-core": "1.131.41", "@tanstack/router-core": "1.131.44",
"@tanstack/router-utils": "1.131.2", "@tanstack/router-utils": "1.131.2",
"@tanstack/virtual-file-routes": "1.131.2", "@tanstack/virtual-file-routes": "1.131.2",
"prettier": "^3.5.0", "prettier": "^3.5.0",
@@ -2383,9 +2409,9 @@
} }
}, },
"node_modules/@tanstack/router-plugin": { "node_modules/@tanstack/router-plugin": {
"version": "1.131.41", "version": "1.131.44",
"resolved": "https://registry.npmjs.org/@tanstack/router-plugin/-/router-plugin-1.131.41.tgz", "resolved": "https://registry.npmjs.org/@tanstack/router-plugin/-/router-plugin-1.131.44.tgz",
"integrity": "sha512-MENVYQwvhKFIPZ/YO/CGCwbh3Ba3TRvUYZ2y2KiU6aa1CWao4KHDRsungzv34AbbUBSmzbc8mKVeqd+G+E9cDQ==", "integrity": "sha512-CvheUPlB8vxXf23RSDz6q97l1EI5H3f+1qJ/LEBvy7bhls8vYouJ3xyTeu4faz8bEEieLUoVQrCcr+xFY0lkuw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -2395,8 +2421,8 @@
"@babel/template": "^7.27.2", "@babel/template": "^7.27.2",
"@babel/traverse": "^7.27.7", "@babel/traverse": "^7.27.7",
"@babel/types": "^7.27.7", "@babel/types": "^7.27.7",
"@tanstack/router-core": "1.131.41", "@tanstack/router-core": "1.131.44",
"@tanstack/router-generator": "1.131.41", "@tanstack/router-generator": "1.131.44",
"@tanstack/router-utils": "1.131.2", "@tanstack/router-utils": "1.131.2",
"@tanstack/virtual-file-routes": "1.131.2", "@tanstack/virtual-file-routes": "1.131.2",
"babel-dead-code-elimination": "^1.0.10", "babel-dead-code-elimination": "^1.0.10",
@@ -2413,7 +2439,7 @@
}, },
"peerDependencies": { "peerDependencies": {
"@rsbuild/core": ">=1.0.2", "@rsbuild/core": ">=1.0.2",
"@tanstack/react-router": "^1.131.41", "@tanstack/react-router": "^1.131.44",
"vite": ">=5.0.0 || >=6.0.0", "vite": ">=5.0.0 || >=6.0.0",
"vite-plugin-solid": "^2.11.2", "vite-plugin-solid": "^2.11.2",
"webpack": ">=5.92.0" "webpack": ">=5.92.0"
@@ -2458,13 +2484,13 @@
} }
}, },
"node_modules/@tanstack/router-vite-plugin": { "node_modules/@tanstack/router-vite-plugin": {
"version": "1.131.41", "version": "1.131.44",
"resolved": "https://registry.npmjs.org/@tanstack/router-vite-plugin/-/router-vite-plugin-1.131.41.tgz", "resolved": "https://registry.npmjs.org/@tanstack/router-vite-plugin/-/router-vite-plugin-1.131.44.tgz",
"integrity": "sha512-UNMLW5BsueJX77lAWwddWGKTDElXS23XfpvaEnxpAPS8rnu+7HEpV4bWciN5VruuTZZM5plP6bXAGec+Bi51Hw==", "integrity": "sha512-5q87hJuT/ybQ3K77Qd649L2curIIh50TIx4OkPCInaqqBeBx101G/6FWubOm2UTl7dVOfDsPPJHcmSbgwvowcA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tanstack/router-plugin": "1.131.41" "@tanstack/router-plugin": "1.131.44"
}, },
"engines": { "engines": {
"node": ">=12" "node": ">=12"
@@ -2556,9 +2582,9 @@
} }
}, },
"node_modules/@types/d3-array": { "node_modules/@types/d3-array": {
"version": "3.2.1", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz",
"integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/d3-color": { "node_modules/@types/d3-color": {
@@ -2633,9 +2659,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "19.1.12", "version": "19.1.13",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.12.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.13.tgz",
"integrity": "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w==", "integrity": "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==",
"devOptional": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -2659,17 +2685,17 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.43.0", "version": "8.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.43.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.0.tgz",
"integrity": "sha512-8tg+gt7ENL7KewsKMKDHXR1vm8tt9eMxjJBYINf6swonlWgkYn5NwyIgXpbbDxTNU5DgpDFfj95prcTq2clIQQ==", "integrity": "sha512-EGDAOGX+uwwekcS0iyxVDmRV9HX6FLSM5kzrAToLTsr9OWCIKG/y3lQheCq18yZ5Xh78rRKJiEpP0ZaCs4ryOQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.43.0", "@typescript-eslint/scope-manager": "8.44.0",
"@typescript-eslint/type-utils": "8.43.0", "@typescript-eslint/type-utils": "8.44.0",
"@typescript-eslint/utils": "8.43.0", "@typescript-eslint/utils": "8.44.0",
"@typescript-eslint/visitor-keys": "8.43.0", "@typescript-eslint/visitor-keys": "8.44.0",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^7.0.0", "ignore": "^7.0.0",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
@@ -2683,7 +2709,7 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"@typescript-eslint/parser": "^8.43.0", "@typescript-eslint/parser": "^8.44.0",
"eslint": "^8.57.0 || ^9.0.0", "eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0" "typescript": ">=4.8.4 <6.0.0"
} }
@@ -2699,16 +2725,16 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.43.0", "version": "8.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.43.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.44.0.tgz",
"integrity": "sha512-B7RIQiTsCBBmY+yW4+ILd6mF5h1FUwJsVvpqkrgpszYifetQ2Ke+Z4u6aZh0CblkUGIdR59iYVyXqqZGkZ3aBw==", "integrity": "sha512-VGMpFQGUQWYT9LfnPcX8ouFojyrZ/2w3K5BucvxL/spdNehccKhB4jUyB1yBCXpr2XFm0jkECxgrpXBW2ipoAw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.43.0", "@typescript-eslint/scope-manager": "8.44.0",
"@typescript-eslint/types": "8.43.0", "@typescript-eslint/types": "8.44.0",
"@typescript-eslint/typescript-estree": "8.43.0", "@typescript-eslint/typescript-estree": "8.44.0",
"@typescript-eslint/visitor-keys": "8.43.0", "@typescript-eslint/visitor-keys": "8.44.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -2724,14 +2750,14 @@
} }
}, },
"node_modules/@typescript-eslint/project-service": { "node_modules/@typescript-eslint/project-service": {
"version": "8.43.0", "version": "8.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.43.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.44.0.tgz",
"integrity": "sha512-htB/+D/BIGoNTQYffZw4uM4NzzuolCoaA/BusuSIcC8YjmBYQioew5VUZAYdAETPjeed0hqCaW7EHg+Robq8uw==", "integrity": "sha512-ZeaGNraRsq10GuEohKTo4295Z/SuGcSq2LzfGlqiuEvfArzo/VRrT0ZaJsVPuKZ55lVbNk8U6FcL+ZMH8CoyVA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.43.0", "@typescript-eslint/tsconfig-utils": "^8.44.0",
"@typescript-eslint/types": "^8.43.0", "@typescript-eslint/types": "^8.44.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -2746,14 +2772,14 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.43.0", "version": "8.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.43.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.44.0.tgz",
"integrity": "sha512-daSWlQ87ZhsjrbMLvpuuMAt3y4ba57AuvadcR7f3nl8eS3BjRc8L9VLxFLk92RL5xdXOg6IQ+qKjjqNEimGuAg==", "integrity": "sha512-87Jv3E+al8wpD+rIdVJm/ItDBe/Im09zXIjFoipOjr5gHUhJmTzfFLuTJ/nPTMc2Srsroy4IBXwcTCHyRR7KzA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.43.0", "@typescript-eslint/types": "8.44.0",
"@typescript-eslint/visitor-keys": "8.43.0" "@typescript-eslint/visitor-keys": "8.44.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2764,9 +2790,9 @@
} }
}, },
"node_modules/@typescript-eslint/tsconfig-utils": { "node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.43.0", "version": "8.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.43.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.0.tgz",
"integrity": "sha512-ALC2prjZcj2YqqL5X/bwWQmHA2em6/94GcbB/KKu5SX3EBDOsqztmmX1kMkvAJHzxk7TazKzJfFiEIagNV3qEA==", "integrity": "sha512-x5Y0+AuEPqAInc6yd0n5DAcvtoQ/vyaGwuX5HE9n6qAefk1GaedqrLQF8kQGylLUb9pnZyLf+iEiL9fr8APDtQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -2781,15 +2807,15 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.43.0", "version": "8.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.43.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.44.0.tgz",
"integrity": "sha512-qaH1uLBpBuBBuRf8c1mLJ6swOfzCXryhKND04Igr4pckzSEW9JX5Aw9AgW00kwfjWJF0kk0ps9ExKTfvXfw4Qg==", "integrity": "sha512-9cwsoSxJ8Sak67Be/hD2RNt/fsqmWnNE1iHohG8lxqLSNY8xNfyY7wloo5zpW3Nu9hxVgURevqfcH6vvKCt6yg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.43.0", "@typescript-eslint/types": "8.44.0",
"@typescript-eslint/typescript-estree": "8.43.0", "@typescript-eslint/typescript-estree": "8.44.0",
"@typescript-eslint/utils": "8.43.0", "@typescript-eslint/utils": "8.44.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^2.1.0" "ts-api-utils": "^2.1.0"
}, },
@@ -2806,9 +2832,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.43.0", "version": "8.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.43.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.44.0.tgz",
"integrity": "sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==", "integrity": "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -2820,16 +2846,16 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.43.0", "version": "8.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.43.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.0.tgz",
"integrity": "sha512-7Vv6zlAhPb+cvEpP06WXXy/ZByph9iL6BQRBDj4kmBsW98AqEeQHlj/13X+sZOrKSo9/rNKH4Ul4f6EICREFdw==", "integrity": "sha512-lqNj6SgnGcQZwL4/SBJ3xdPEfcBuhCG8zdcwCPgYcmiPLgokiNDKlbPzCwEwu7m279J/lBYWtDYL+87OEfn8Jw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/project-service": "8.43.0", "@typescript-eslint/project-service": "8.44.0",
"@typescript-eslint/tsconfig-utils": "8.43.0", "@typescript-eslint/tsconfig-utils": "8.44.0",
"@typescript-eslint/types": "8.43.0", "@typescript-eslint/types": "8.44.0",
"@typescript-eslint/visitor-keys": "8.43.0", "@typescript-eslint/visitor-keys": "8.44.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@@ -2888,16 +2914,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.43.0", "version": "8.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.43.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.44.0.tgz",
"integrity": "sha512-S1/tEmkUeeswxd0GGcnwuVQPFWo8NzZTOMxCvw8BX7OMxnNae+i8Tm7REQen/SwUIPoPqfKn7EaZ+YLpiB3k9g==", "integrity": "sha512-nktOlVcg3ALo0mYlV+L7sWUD58KG4CMj1rb2HUVOO4aL3K/6wcD+NERqd0rrA5Vg06b42YhF6cFxeixsp9Riqg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.7.0", "@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.43.0", "@typescript-eslint/scope-manager": "8.44.0",
"@typescript-eslint/types": "8.43.0", "@typescript-eslint/types": "8.44.0",
"@typescript-eslint/typescript-estree": "8.43.0" "@typescript-eslint/typescript-estree": "8.44.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2912,13 +2938,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.43.0", "version": "8.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.43.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.0.tgz",
"integrity": "sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==", "integrity": "sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.43.0", "@typescript-eslint/types": "8.44.0",
"eslint-visitor-keys": "^4.2.1" "eslint-visitor-keys": "^4.2.1"
}, },
"engines": { "engines": {
@@ -3126,9 +3152,9 @@
} }
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.12.1", "version": "1.12.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.1.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
"integrity": "sha512-Kn4kbSXpkFHCGE6rBFNwIv0GQs4AvDT80jlveJDKFxjbTYMUeB4QtsdPCv6H8Cm19Je7IU6VFtRl2zWZI0rudQ==", "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
@@ -3156,9 +3182,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/baseline-browser-mapping": { "node_modules/baseline-browser-mapping": {
"version": "2.8.2", "version": "2.8.4",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.2.tgz", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.4.tgz",
"integrity": "sha512-NvcIedLxrs9llVpX7wI+Jz4Hn9vJQkCPKrTaHIE0sW/Rj1iq6Fzby4NbyTZjQJNoypBXNaG7tEHkTgONZpwgxQ==", "integrity": "sha512-L+YvJwGAgwJBV1p6ffpSTa2KRc69EeeYGYjRVWKs0GKrK+LON0GC0gV+rKSNtALEDvMDqkvCFq9r1r94/Gjwxw==",
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
"baseline-browser-mapping": "dist/cli.js" "baseline-browser-mapping": "dist/cli.js"
@@ -3200,9 +3226,9 @@
} }
}, },
"node_modules/browserslist": { "node_modules/browserslist": {
"version": "4.26.0", "version": "4.26.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.0.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz",
"integrity": "sha512-P9go2WrP9FiPwLv3zqRD/Uoxo0RSHjzFCiQz7d4vbmwNqQFo9T9WCeP/Qn5EbcKQY6DBbkxEXNcpJOmncNrb7A==", "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -3219,7 +3245,7 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"baseline-browser-mapping": "^2.8.2", "baseline-browser-mapping": "^2.8.3",
"caniuse-lite": "^1.0.30001741", "caniuse-lite": "^1.0.30001741",
"electron-to-chromium": "^1.5.218", "electron-to-chromium": "^1.5.218",
"node-releases": "^2.0.21", "node-releases": "^2.0.21",
@@ -3265,9 +3291,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001741", "version": "1.0.30001743",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz",
"integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==", "integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -3663,9 +3689,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/debug": { "node_modules/debug": {
"version": "4.4.1", "version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ms": "^2.1.3" "ms": "^2.1.3"
@@ -5171,9 +5197,19 @@
} }
}, },
"node_modules/postcss-js": { "node_modules/postcss-js": {
"version": "4.0.1", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz",
"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"camelcase-css": "^2.0.1" "camelcase-css": "^2.0.1"
@@ -5181,10 +5217,6 @@
"engines": { "engines": {
"node": "^12 || ^14 || >= 16" "node": "^12 || ^14 || >= 16"
}, },
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": { "peerDependencies": {
"postcss": "^8.4.21" "postcss": "^8.4.21"
} }
@@ -5527,9 +5559,9 @@
} }
}, },
"node_modules/recharts": { "node_modules/recharts": {
"version": "3.2.0", "version": "3.2.1",
"resolved": "https://registry.npmjs.org/recharts/-/recharts-3.2.0.tgz", "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.2.1.tgz",
"integrity": "sha512-fX0xCgNXo6mag9wz3oLuANR+dUQM4uIlTYBGTGq9CBRgW/8TZPzqPGYs5NTt8aENCf+i1CI8vqxT1py8L/5J2w==", "integrity": "sha512-0JKwHRiFZdmLq/6nmilxEZl3pqb4T+aKkOkOi/ZISRZwfBhVMgInxzlYU9D4KnCH3KINScLy68m/OvMXoYGZUw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "1.x.x || 2.x.x", "@reduxjs/toolkit": "1.x.x || 2.x.x",
@@ -5633,9 +5665,9 @@
} }
}, },
"node_modules/rollup": { "node_modules/rollup": {
"version": "4.50.1", "version": "4.50.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.1.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.2.tgz",
"integrity": "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA==", "integrity": "sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -5649,27 +5681,27 @@
"npm": ">=8.0.0" "npm": ">=8.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.50.1", "@rollup/rollup-android-arm-eabi": "4.50.2",
"@rollup/rollup-android-arm64": "4.50.1", "@rollup/rollup-android-arm64": "4.50.2",
"@rollup/rollup-darwin-arm64": "4.50.1", "@rollup/rollup-darwin-arm64": "4.50.2",
"@rollup/rollup-darwin-x64": "4.50.1", "@rollup/rollup-darwin-x64": "4.50.2",
"@rollup/rollup-freebsd-arm64": "4.50.1", "@rollup/rollup-freebsd-arm64": "4.50.2",
"@rollup/rollup-freebsd-x64": "4.50.1", "@rollup/rollup-freebsd-x64": "4.50.2",
"@rollup/rollup-linux-arm-gnueabihf": "4.50.1", "@rollup/rollup-linux-arm-gnueabihf": "4.50.2",
"@rollup/rollup-linux-arm-musleabihf": "4.50.1", "@rollup/rollup-linux-arm-musleabihf": "4.50.2",
"@rollup/rollup-linux-arm64-gnu": "4.50.1", "@rollup/rollup-linux-arm64-gnu": "4.50.2",
"@rollup/rollup-linux-arm64-musl": "4.50.1", "@rollup/rollup-linux-arm64-musl": "4.50.2",
"@rollup/rollup-linux-loongarch64-gnu": "4.50.1", "@rollup/rollup-linux-loong64-gnu": "4.50.2",
"@rollup/rollup-linux-ppc64-gnu": "4.50.1", "@rollup/rollup-linux-ppc64-gnu": "4.50.2",
"@rollup/rollup-linux-riscv64-gnu": "4.50.1", "@rollup/rollup-linux-riscv64-gnu": "4.50.2",
"@rollup/rollup-linux-riscv64-musl": "4.50.1", "@rollup/rollup-linux-riscv64-musl": "4.50.2",
"@rollup/rollup-linux-s390x-gnu": "4.50.1", "@rollup/rollup-linux-s390x-gnu": "4.50.2",
"@rollup/rollup-linux-x64-gnu": "4.50.1", "@rollup/rollup-linux-x64-gnu": "4.50.2",
"@rollup/rollup-linux-x64-musl": "4.50.1", "@rollup/rollup-linux-x64-musl": "4.50.2",
"@rollup/rollup-openharmony-arm64": "4.50.1", "@rollup/rollup-openharmony-arm64": "4.50.2",
"@rollup/rollup-win32-arm64-msvc": "4.50.1", "@rollup/rollup-win32-arm64-msvc": "4.50.2",
"@rollup/rollup-win32-ia32-msvc": "4.50.1", "@rollup/rollup-win32-ia32-msvc": "4.50.2",
"@rollup/rollup-win32-x64-msvc": "4.50.1", "@rollup/rollup-win32-x64-msvc": "4.50.2",
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
@@ -5765,6 +5797,16 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/sonner": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz",
"integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==",
"license": "MIT",
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc",
"react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc"
}
},
"node_modules/source-map": { "node_modules/source-map": {
"version": "0.7.6", "version": "0.7.6",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
@@ -6172,16 +6214,16 @@
} }
}, },
"node_modules/typescript-eslint": { "node_modules/typescript-eslint": {
"version": "8.43.0", "version": "8.44.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.43.0.tgz", "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.44.0.tgz",
"integrity": "sha512-FyRGJKUGvcFekRRcBKFBlAhnp4Ng8rhe8tuvvkR9OiU0gfd4vyvTRQHEckO6VDlH57jbeUQem2IpqPq9kLJH+w==", "integrity": "sha512-ib7mCkYuIzYonCq9XWF5XNw+fkj2zg629PSa9KNIQ47RXFF763S5BIX4wqz1+FLPogTZoiw8KmCiRPRa8bL3qw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/eslint-plugin": "8.43.0", "@typescript-eslint/eslint-plugin": "8.44.0",
"@typescript-eslint/parser": "8.43.0", "@typescript-eslint/parser": "8.44.0",
"@typescript-eslint/typescript-estree": "8.43.0", "@typescript-eslint/typescript-estree": "8.44.0",
"@typescript-eslint/utils": "8.43.0" "@typescript-eslint/utils": "8.44.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"

View File

@@ -12,6 +12,7 @@
"dependencies": { "dependencies": {
"@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-progress": "^1.1.7",
"@radix-ui/react-select": "^2.2.6", "@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-slot": "^1.2.3",
"@tailwindcss/forms": "^0.5.10", "@tailwindcss/forms": "^0.5.10",
@@ -31,6 +32,7 @@
"react-day-picker": "^9.10.0", "react-day-picker": "^9.10.0",
"react-dom": "^19.1.1", "react-dom": "^19.1.1",
"recharts": "^3.2.0", "recharts": "^3.2.0",
"sonner": "^2.0.7",
"tailwind-merge": "^3.3.1", "tailwind-merge": "^3.3.1",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"tailwindcss-animate": "^1.0.7" "tailwindcss-animate": "^1.0.7"

View File

@@ -22,7 +22,7 @@ import {
} from "./ui/card"; } from "./ui/card";
import { Button } from "./ui/button"; import { Button } from "./ui/button";
import { Alert, AlertDescription, AlertTitle } from "./ui/alert"; import { Alert, AlertDescription, AlertTitle } from "./ui/alert";
import LoadingSpinner from "./LoadingSpinner"; import AccountsSkeleton from "./AccountsSkeleton";
import type { Account, Balance } from "../types/api"; import type { Account, Balance } from "../types/api";
// Helper function to get status indicator color and styles // Helper function to get status indicator color and styles
@@ -37,23 +37,23 @@ const getStatusIndicator = (status: string) => {
}; };
case "pending": case "pending":
return { return {
color: "bg-yellow-500", color: "bg-amber-500",
tooltip: "Pending", tooltip: "Pending",
}; };
case "error": case "error":
case "failed": case "failed":
return { return {
color: "bg-red-500", color: "bg-destructive",
tooltip: "Error", tooltip: "Error",
}; };
case "inactive": case "inactive":
return { return {
color: "bg-gray-500", color: "bg-muted-foreground",
tooltip: "Inactive", tooltip: "Inactive",
}; };
default: default:
return { return {
color: "bg-blue-500", color: "bg-primary",
tooltip: status, tooltip: status,
}; };
} }
@@ -114,11 +114,7 @@ export default function AccountsOverview() {
}; };
if (accountsLoading) { if (accountsLoading) {
return ( return <AccountsSkeleton />;
<Card>
<LoadingSpinner message="Loading accounts..." />
</Card>
);
} }
if (accountsError) { if (accountsError) {
@@ -201,8 +197,8 @@ export default function AccountsOverview() {
{uniqueBanks} {uniqueBanks}
</p> </p>
</div> </div>
<div className="p-3 bg-purple-100 dark:bg-purple-900/20 rounded-full"> <div className="p-3 bg-muted rounded-full">
<Building2 className="h-6 w-6 text-purple-600" /> <Building2 className="h-6 w-6 text-muted-foreground" />
</div> </div>
</div> </div>
</CardContent> </CardContent>
@@ -304,7 +300,9 @@ export default function AccountsOverview() {
<div> <div>
<div className="flex items-center space-x-2 min-w-0"> <div className="flex items-center space-x-2 min-w-0">
<h4 className="text-base sm:text-lg font-medium text-foreground truncate"> <h4 className="text-base sm:text-lg font-medium text-foreground truncate">
{account.display_name || account.name || "Unnamed Account"} {account.display_name ||
account.name ||
"Unnamed Account"}
</h4> </h4>
<button <button
onClick={() => handleEditStart(account)} onClick={() => handleEditStart(account)}

View File

@@ -0,0 +1,61 @@
import { Skeleton } from "./ui/skeleton";
import { Card, CardContent, CardHeader } from "./ui/card";
export default function AccountsSkeleton() {
return (
<div className="space-y-6">
{/* Summary Cards Skeleton */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{Array.from({ length: 3 }).map((_, i) => (
<Card key={i}>
<CardContent className="p-6">
<div className="flex items-center justify-between">
<div className="space-y-2">
<Skeleton className="h-4 w-20" />
<Skeleton className="h-8 w-24" />
</div>
<Skeleton className="h-12 w-12 rounded-full" />
</div>
</CardContent>
</Card>
))}
</div>
{/* Accounts List Skeleton */}
<Card>
<CardHeader>
<Skeleton className="h-6 w-32" />
<Skeleton className="h-4 w-48" />
</CardHeader>
<CardContent className="p-0">
<div className="divide-y divide-border">
{Array.from({ length: 4 }).map((_, i) => (
<div key={i} className="p-4 sm:p-6">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 sm:gap-4">
<div className="flex items-start sm:items-center space-x-3 sm:space-x-4 min-w-0 flex-1">
<Skeleton className="h-10 w-10 sm:h-12 sm:w-12 rounded-full flex-shrink-0" />
<div className="flex-1 space-y-2">
<Skeleton className="h-5 w-48" />
<Skeleton className="h-4 w-32" />
<Skeleton className="h-3 w-40" />
</div>
</div>
<div className="flex items-center justify-between sm:flex-col sm:items-end sm:text-right flex-shrink-0">
<div className="flex items-center space-x-2 order-1 sm:order-2">
<Skeleton className="h-3 w-3 rounded-full" />
<Skeleton className="h-4 w-20" />
</div>
<div className="flex items-center space-x-2 order-2 sm:order-1">
<Skeleton className="h-4 w-4" />
<Skeleton className="h-5 w-24" />
</div>
</div>
</div>
</div>
))}
</div>
</CardContent>
</Card>
</div>
);
}

View File

@@ -1,6 +1,9 @@
import { Component } from "react"; import { Component } from "react";
import type { ErrorInfo, ReactNode } from "react"; import type { ErrorInfo, ReactNode } from "react";
import { AlertTriangle, RefreshCw } from "lucide-react"; import { AlertTriangle, RefreshCw } from "lucide-react";
import { Card, CardContent } from "./ui/card";
import { Alert, AlertDescription, AlertTitle } from "./ui/alert";
import { Button } from "./ui/button";
interface Props { interface Props {
children: ReactNode; children: ReactNode;
@@ -39,46 +42,49 @@ class ErrorBoundary extends Component<Props, State> {
} }
return ( return (
<div className="bg-white rounded-lg shadow p-6"> <Card>
<div className="flex items-center justify-center text-center"> <CardContent className="p-6">
<div> <div className="flex items-center justify-center text-center">
<AlertTriangle className="h-12 w-12 text-red-400 mx-auto mb-4" /> <div>
<h3 className="text-lg font-medium text-gray-900 mb-2"> <AlertTriangle className="h-12 w-12 text-destructive mx-auto mb-4" />
Something went wrong <h3 className="text-lg font-medium text-foreground mb-2">
</h3> Something went wrong
<p className="text-gray-600 mb-4"> </h3>
An error occurred while rendering this component. Please try <p className="text-muted-foreground mb-4">
refreshing or check the console for more details. An error occurred while rendering this component. Please try
</p> refreshing or check the console for more details.
</p>
{this.state.error && ( {this.state.error && (
<div className="bg-red-50 border border-red-200 rounded-md p-3 mb-4 text-left"> <Alert variant="destructive" className="mb-4 text-left">
<p className="text-sm font-mono text-red-800"> <AlertTriangle className="h-4 w-4" />
<strong>Error:</strong> {this.state.error.message} <AlertTitle>Error Details</AlertTitle>
</p> <AlertDescription className="space-y-2">
{this.state.error.stack && ( <p className="text-sm font-mono">
<details className="mt-2"> <strong>Error:</strong> {this.state.error.message}
<summary className="text-sm text-red-600 cursor-pointer"> </p>
Stack trace {this.state.error.stack && (
</summary> <details className="mt-2">
<pre className="text-xs text-red-700 mt-1 whitespace-pre-wrap"> <summary className="text-sm cursor-pointer">
{this.state.error.stack} Stack trace
</pre> </summary>
</details> <pre className="text-xs mt-1 whitespace-pre-wrap">
)} {this.state.error.stack}
</div> </pre>
)} </details>
)}
</AlertDescription>
</Alert>
)}
<button <Button onClick={this.handleReset}>
onClick={this.handleReset} <RefreshCw className="h-4 w-4 mr-2" />
className="inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors" Try Again
> </Button>
<RefreshCw className="h-4 w-4 mr-2" /> </div>
Try Again
</button>
</div> </div>
</div> </CardContent>
</div> </Card>
); );
} }

View File

@@ -1,29 +1,32 @@
import { Skeleton } from "./ui/skeleton";
import { Card, CardContent } from "./ui/card";
export default function FiltersSkeleton() { export default function FiltersSkeleton() {
return ( return (
<div className="bg-white rounded-lg shadow animate-pulse"> <Card>
<div className="px-6 py-4 border-b border-gray-200"> <div className="px-6 py-4 border-b border-border">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="h-6 bg-gray-200 rounded w-32"></div> <Skeleton className="h-6 w-32" />
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<div className="h-8 bg-gray-200 rounded w-24"></div> <Skeleton className="h-8 w-24" />
<div className="h-8 bg-gray-200 rounded w-20"></div> <Skeleton className="h-8 w-20" />
</div> </div>
</div> </div>
</div> </div>
<div className="px-6 py-4 border-b border-gray-200 bg-gray-50"> <CardContent className="px-6 py-4 border-b border-border bg-muted/30">
{/* Quick Date Filters Skeleton */} {/* Quick Date Filters Skeleton */}
<div className="mb-6"> <div className="mb-6">
<div className="h-4 bg-gray-200 rounded w-32 mb-3"></div> <Skeleton className="h-4 w-32 mb-3" />
<div className="space-y-2"> <div className="space-y-2">
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
<div className="h-10 bg-gray-200 rounded-lg w-24"></div> <Skeleton className="h-10 w-24 rounded-lg" />
<div className="h-10 bg-gray-200 rounded-lg w-20"></div> <Skeleton className="h-10 w-20 rounded-lg" />
<div className="h-10 bg-gray-200 rounded-lg w-28"></div> <Skeleton className="h-10 w-28 rounded-lg" />
</div> </div>
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
<div className="h-10 bg-gray-200 rounded-lg w-24"></div> <Skeleton className="h-10 w-24 rounded-lg" />
<div className="h-10 bg-gray-200 rounded-lg w-20"></div> <Skeleton className="h-10 w-20 rounded-lg" />
</div> </div>
</div> </div>
</div> </div>
@@ -31,40 +34,40 @@ export default function FiltersSkeleton() {
{/* Filter Fields Skeleton */} {/* Filter Fields Skeleton */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<div className="sm:col-span-2 lg:col-span-1"> <div className="sm:col-span-2 lg:col-span-1">
<div className="h-4 bg-gray-200 rounded w-16 mb-1"></div> <Skeleton className="h-4 w-16 mb-1" />
<div className="h-10 bg-gray-200 rounded"></div> <Skeleton className="h-10 w-full" />
</div> </div>
<div> <div>
<div className="h-4 bg-gray-200 rounded w-16 mb-1"></div> <Skeleton className="h-4 w-16 mb-1" />
<div className="h-10 bg-gray-200 rounded"></div> <Skeleton className="h-10 w-full" />
</div> </div>
<div> <div>
<div className="h-4 bg-gray-200 rounded w-20 mb-1"></div> <Skeleton className="h-4 w-20 mb-1" />
<div className="h-10 bg-gray-200 rounded"></div> <Skeleton className="h-10 w-full" />
</div> </div>
<div> <div>
<div className="h-4 bg-gray-200 rounded w-16 mb-1"></div> <Skeleton className="h-4 w-16 mb-1" />
<div className="h-10 bg-gray-200 rounded"></div> <Skeleton className="h-10 w-full" />
</div> </div>
</div> </div>
{/* Amount Range Filters Skeleton */} {/* Amount Range Filters Skeleton */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mt-4"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mt-4">
<div> <div>
<div className="h-4 bg-gray-200 rounded w-20 mb-1"></div> <Skeleton className="h-4 w-20 mb-1" />
<div className="h-10 bg-gray-200 rounded"></div> <Skeleton className="h-10 w-full" />
</div> </div>
<div> <div>
<div className="h-4 bg-gray-200 rounded w-20 mb-1"></div> <Skeleton className="h-4 w-20 mb-1" />
<div className="h-10 bg-gray-200 rounded"></div> <Skeleton className="h-10 w-full" />
</div> </div>
</div> </div>
</div> </CardContent>
{/* Results Summary Skeleton */} {/* Results Summary Skeleton */}
<div className="px-6 py-3 bg-gray-50 border-b border-gray-200"> <CardContent className="px-6 py-3 bg-muted/30 border-b border-border">
<div className="h-4 bg-gray-200 rounded w-48"></div> <Skeleton className="h-4 w-48" />
</div> </CardContent>
</div> </Card>
); );
} }

View File

@@ -49,15 +49,15 @@ export default function Header({ setSidebarOpen }: HeaderProps) {
<div className="flex items-center space-x-1"> <div className="flex items-center space-x-1">
{healthLoading ? ( {healthLoading ? (
<> <>
<Activity className="h-4 w-4 text-yellow-500 animate-pulse" /> <Activity className="h-4 w-4 text-muted-foreground animate-pulse" />
<span className="text-sm text-muted-foreground"> <span className="text-sm text-muted-foreground">
Checking... Checking...
</span> </span>
</> </>
) : healthError || healthStatus?.status !== "healthy" ? ( ) : healthError || healthStatus?.status !== "healthy" ? (
<> <>
<WifiOff className="h-4 w-4 text-red-500" /> <WifiOff className="h-4 w-4 text-destructive" />
<span className="text-sm text-red-500">Disconnected</span> <span className="text-sm text-destructive">Disconnected</span>
</> </>
) : ( ) : (
<> <>

View File

@@ -1,18 +0,0 @@
import { RefreshCw } from "lucide-react";
interface LoadingSpinnerProps {
message?: string;
}
export default function LoadingSpinner({
message = "Loading...",
}: LoadingSpinnerProps) {
return (
<div className="flex items-center justify-center p-8">
<div className="text-center">
<RefreshCw className="h-8 w-8 animate-spin text-blue-600 mx-auto mb-2" />
<p className="text-gray-600 text-sm">{message}</p>
</div>
</div>
);
}

View File

@@ -12,7 +12,7 @@ import {
TestTube, TestTube,
} from "lucide-react"; } from "lucide-react";
import { apiClient } from "../lib/api"; import { apiClient } from "../lib/api";
import LoadingSpinner from "./LoadingSpinner"; import NotificationsSkeleton from "./NotificationsSkeleton";
import { import {
Card, Card,
CardContent, CardContent,
@@ -24,6 +24,7 @@ import { Alert, AlertDescription, AlertTitle } from "./ui/alert";
import { Button } from "./ui/button"; import { Button } from "./ui/button";
import { Input } from "./ui/input"; import { Input } from "./ui/input";
import { Label } from "./ui/label"; import { Label } from "./ui/label";
import { Badge } from "./ui/badge";
import { import {
Select, Select,
SelectContent, SelectContent,
@@ -80,11 +81,7 @@ export default function Notifications() {
}); });
if (settingsLoading || servicesLoading) { if (settingsLoading || servicesLoading) {
return ( return <NotificationsSkeleton />;
<Card>
<LoadingSpinner message="Loading notifications..." />
</Card>
);
} }
if (settingsError || servicesError) { if (settingsError || servicesError) {
@@ -233,12 +230,10 @@ export default function Notifications() {
{service.name} {service.name}
</h4> </h4>
<div className="flex items-center space-x-2 mt-1"> <div className="flex items-center space-x-2 mt-1">
<span <Badge
className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${ variant={
service.enabled service.enabled ? "default" : "destructive"
? "bg-green-100 text-green-800" }
: "bg-red-100 text-red-800"
}`}
> >
{service.enabled ? ( {service.enabled ? (
<CheckCircle className="h-3 w-3 mr-1" /> <CheckCircle className="h-3 w-3 mr-1" />
@@ -246,18 +241,16 @@ export default function Notifications() {
<AlertCircle className="h-3 w-3 mr-1" /> <AlertCircle className="h-3 w-3 mr-1" />
)} )}
{service.enabled ? "Enabled" : "Disabled"} {service.enabled ? "Enabled" : "Disabled"}
</span> </Badge>
<span <Badge
className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${ variant={
service.configured service.configured ? "secondary" : "outline"
? "bg-blue-100 text-blue-800" }
: "bg-yellow-100 text-yellow-800"
}`}
> >
{service.configured {service.configured
? "Configured" ? "Configured"
: "Not Configured"} : "Not Configured"}
</span> </Badge>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,95 @@
import { Skeleton } from "./ui/skeleton";
import { Card, CardContent, CardHeader } from "./ui/card";
export default function NotificationsSkeleton() {
return (
<div className="space-y-6">
{/* Test Notification Section Skeleton */}
<Card>
<CardHeader>
<div className="flex items-center space-x-2">
<Skeleton className="h-5 w-5" />
<Skeleton className="h-6 w-36" />
</div>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Skeleton className="h-4 w-16" />
<Skeleton className="h-10 w-full" />
</div>
<div className="space-y-2">
<Skeleton className="h-4 w-16" />
<Skeleton className="h-10 w-full" />
</div>
</div>
<div className="mt-4">
<Skeleton className="h-10 w-48" />
</div>
</CardContent>
</Card>
{/* Notification Services Skeleton */}
<Card>
<CardHeader>
<div className="flex items-center space-x-2">
<Skeleton className="h-5 w-5" />
<Skeleton className="h-6 w-40" />
</div>
<Skeleton className="h-4 w-56" />
</CardHeader>
<CardContent className="p-0">
<div className="divide-y divide-border">
{Array.from({ length: 3 }).map((_, i) => (
<div key={i} className="p-6">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-4">
<Skeleton className="h-12 w-12 rounded-full" />
<div className="space-y-2">
<Skeleton className="h-5 w-24" />
<div className="flex items-center space-x-2">
<Skeleton className="h-5 w-16" />
<Skeleton className="h-5 w-20" />
</div>
</div>
</div>
<Skeleton className="h-8 w-8" />
</div>
</div>
))}
</div>
</CardContent>
</Card>
{/* Notification Settings Skeleton */}
<Card>
<CardHeader>
<div className="flex items-center space-x-2">
<Skeleton className="h-5 w-5" />
<Skeleton className="h-6 w-40" />
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="space-y-2">
<Skeleton className="h-4 w-16" />
<div className="bg-muted rounded-md p-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="space-y-2">
<Skeleton className="h-3 w-32" />
<Skeleton className="h-4 w-24" />
</div>
<div className="space-y-2">
<Skeleton className="h-3 w-28" />
<Skeleton className="h-4 w-20" />
</div>
</div>
</div>
</div>
<Skeleton className="h-12 w-full" />
</div>
</CardContent>
</Card>
</div>
);
}

View File

@@ -1,3 +1,6 @@
import { Skeleton } from "./ui/skeleton";
import { Card } from "./ui/card";
interface TransactionSkeletonProps { interface TransactionSkeletonProps {
rows?: number; rows?: number;
view?: "table" | "mobile"; view?: "table" | "mobile";
@@ -11,93 +14,89 @@ export default function TransactionSkeleton({
if (view === "mobile") { if (view === "mobile") {
return ( return (
<div className="bg-white rounded-lg shadow divide-y divide-gray-200"> <Card className="divide-y divide-border">
{skeletonRows.map((_, index) => ( {skeletonRows.map((_, index) => (
<div key={index} className="p-4 animate-pulse"> <div key={index} className="p-4">
<div className="flex items-start justify-between"> <div className="flex items-start justify-between">
<div className="flex-1"> <div className="flex-1">
<div className="flex items-start space-x-3"> <div className="flex items-start space-x-3">
<div className="p-2 rounded-full bg-gray-200 flex-shrink-0"> <Skeleton className="h-10 w-10 rounded-full flex-shrink-0" />
<div className="h-4 w-4 bg-gray-300 rounded"></div>
</div>
<div className="flex-1 min-w-0 space-y-2"> <div className="flex-1 min-w-0 space-y-2">
<div className="h-4 bg-gray-200 rounded w-3/4"></div> <Skeleton className="h-4 w-3/4" />
<div className="space-y-1"> <div className="space-y-1">
<div className="h-3 bg-gray-200 rounded w-1/2"></div> <Skeleton className="h-3 w-1/2" />
<div className="h-3 bg-gray-200 rounded w-2/3"></div> <Skeleton className="h-3 w-2/3" />
<div className="h-3 bg-gray-200 rounded w-1/3"></div> <Skeleton className="h-3 w-1/3" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div className="text-right ml-3 flex-shrink-0 space-y-2"> <div className="text-right ml-3 flex-shrink-0 space-y-2">
<div className="h-6 bg-gray-200 rounded w-20"></div> <Skeleton className="h-6 w-20" />
<div className="h-4 bg-gray-200 rounded w-16 ml-auto"></div> <Skeleton className="h-4 w-16 ml-auto" />
<div className="h-6 bg-gray-200 rounded w-12 ml-auto"></div> <Skeleton className="h-6 w-12 ml-auto" />
</div> </div>
</div> </div>
</div> </div>
))} ))}
</div> </Card>
); );
} }
return ( return (
<div className="bg-white rounded-lg shadow overflow-hidden"> <Card className="overflow-hidden">
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200"> <table className="min-w-full divide-y divide-border">
<thead className="bg-gray-50"> <thead className="bg-muted/50">
<tr> <tr>
<th className="px-6 py-3 text-left"> <th className="px-6 py-3 text-left">
<div className="h-4 bg-gray-200 rounded w-20 animate-pulse"></div> <Skeleton className="h-4 w-20" />
</th> </th>
<th className="px-6 py-3 text-left"> <th className="px-6 py-3 text-left">
<div className="h-4 bg-gray-200 rounded w-16 animate-pulse"></div> <Skeleton className="h-4 w-16" />
</th> </th>
<th className="px-6 py-3 text-left"> <th className="px-6 py-3 text-left">
<div className="h-4 bg-gray-200 rounded w-12 animate-pulse"></div> <Skeleton className="h-4 w-12" />
</th> </th>
<th className="px-6 py-3 text-left"> <th className="px-6 py-3 text-left">
<div className="h-4 bg-gray-200 rounded w-8 animate-pulse"></div> <Skeleton className="h-4 w-8" />
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody className="bg-white divide-y divide-gray-200"> <tbody className="bg-card divide-y divide-border">
{skeletonRows.map((_, index) => ( {skeletonRows.map((_, index) => (
<tr key={index} className="animate-pulse"> <tr key={index}>
<td className="px-6 py-4"> <td className="px-6 py-4">
<div className="flex items-start space-x-3"> <div className="flex items-start space-x-3">
<div className="p-2 rounded-full bg-gray-200 flex-shrink-0"> <Skeleton className="h-10 w-10 rounded-full flex-shrink-0" />
<div className="h-4 w-4 bg-gray-300 rounded"></div>
</div>
<div className="flex-1 space-y-2"> <div className="flex-1 space-y-2">
<div className="h-4 bg-gray-200 rounded w-3/4"></div> <Skeleton className="h-4 w-3/4" />
<div className="space-y-1"> <div className="space-y-1">
<div className="h-3 bg-gray-200 rounded w-1/2"></div> <Skeleton className="h-3 w-1/2" />
<div className="h-3 bg-gray-200 rounded w-2/3"></div> <Skeleton className="h-3 w-2/3" />
</div> </div>
</div> </div>
</div> </div>
</td> </td>
<td className="px-6 py-4"> <td className="px-6 py-4">
<div className="text-right"> <div className="text-right">
<div className="h-6 bg-gray-200 rounded w-24 ml-auto mb-1"></div> <Skeleton className="h-6 w-24 ml-auto mb-1" />
</div> </div>
</td> </td>
<td className="px-6 py-4"> <td className="px-6 py-4">
<div className="space-y-1"> <div className="space-y-1">
<div className="h-4 bg-gray-200 rounded w-20"></div> <Skeleton className="h-4 w-20" />
<div className="h-3 bg-gray-200 rounded w-16"></div> <Skeleton className="h-3 w-16" />
</div> </div>
</td> </td>
<td className="px-6 py-4"> <td className="px-6 py-4">
<div className="h-6 bg-gray-200 rounded w-12"></div> <Skeleton className="h-6 w-12" />
</td> </td>
</tr> </tr>
))} ))}
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </Card>
); );
} }

View File

@@ -17,6 +17,7 @@ interface PieDataPoint {
name: string; name: string;
value: number; value: number;
color: string; color: string;
[key: string]: string | number;
} }
interface TooltipProps { interface TooltipProps {

View File

@@ -38,7 +38,8 @@ export function AccountCombobox({
); );
const formatAccountName = (account: Account) => { const formatAccountName = (account: Account) => {
const displayName = account.display_name || account.name || "Unnamed Account"; const displayName =
account.display_name || account.name || "Unnamed Account";
return `${displayName} (${account.institution_id})`; return `${displayName} (${account.institution_id})`;
}; };
@@ -105,7 +106,9 @@ export function AccountCombobox({
/> />
<div className="flex flex-col"> <div className="flex flex-col">
<span className="font-medium"> <span className="font-medium">
{account.display_name || account.name || "Unnamed Account"} {account.display_name ||
account.name ||
"Unnamed Account"}
</span> </span>
<span className="text-xs text-gray-500"> <span className="text-xs text-gray-500">
{account.institution_id} {account.institution_id}

View File

@@ -4,7 +4,7 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
const alertVariants = cva( const alertVariants = cva(
"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
{ {
variants: { variants: {
variant: { variant: {

View File

@@ -0,0 +1,26 @@
import * as React from "react";
import * as ProgressPrimitive from "@radix-ui/react-progress";
import { cn } from "@/lib/utils";
const Progress = React.forwardRef<
React.ElementRef<typeof ProgressPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
>(({ className, value, ...props }, ref) => (
<ProgressPrimitive.Root
ref={ref}
className={cn(
"relative h-2 w-full overflow-hidden rounded-full bg-secondary",
className,
)}
{...props}
>
<ProgressPrimitive.Indicator
className="h-full w-full flex-1 bg-primary transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>
));
Progress.displayName = ProgressPrimitive.Root.displayName;
export { Progress };

View File

@@ -0,0 +1,138 @@
import * as React from "react";
import * as SheetPrimitive from "@radix-ui/react-dialog";
import { cva, type VariantProps } from "class-variance-authority";
import { X } from "lucide-react";
import { cn } from "@/lib/utils";
const Sheet = SheetPrimitive.Root;
const SheetTrigger = SheetPrimitive.Trigger;
const SheetClose = SheetPrimitive.Close;
const SheetPortal = SheetPrimitive.Portal;
const SheetOverlay = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Overlay
className={cn(
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className,
)}
{...props}
ref={ref}
/>
));
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
const sheetVariants = cva(
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
{
variants: {
side: {
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
bottom:
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
right:
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
},
},
defaultVariants: {
side: "right",
},
},
);
interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {}
const SheetContent = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Content>,
SheetContentProps
>(({ side = "right", className, children, ...props }, ref) => (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content
ref={ref}
className={cn(sheetVariants({ side }), className)}
{...props}
>
{children}
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
</SheetPrimitive.Content>
</SheetPortal>
));
SheetContent.displayName = SheetPrimitive.Content.displayName;
const SheetHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className,
)}
{...props}
/>
);
SheetHeader.displayName = "SheetHeader";
const SheetFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className,
)}
{...props}
/>
);
SheetFooter.displayName = "SheetFooter";
const SheetTitle = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Title
ref={ref}
className={cn("text-lg font-semibold text-foreground", className)}
{...props}
/>
));
SheetTitle.displayName = SheetPrimitive.Title.displayName;
const SheetDescription = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
));
SheetDescription.displayName = SheetPrimitive.Description.displayName;
export {
Sheet,
SheetPortal,
SheetOverlay,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
};

View File

@@ -0,0 +1,15 @@
import { cn } from "@/lib/utils";
function Skeleton({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={cn("animate-pulse rounded-md bg-muted", className)}
{...props}
/>
);
}
export { Skeleton };

View File

@@ -0,0 +1,27 @@
"use client";
import { Toaster as Sonner } from "sonner";
type ToasterProps = React.ComponentProps<typeof Sonner>;
const Toaster = ({ ...props }: ToasterProps) => {
return (
<Sonner
className="toaster group"
toastOptions={{
classNames: {
toast:
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
description: "group-[.toast]:text-muted-foreground",
actionButton:
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
cancelButton:
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
},
}}
{...props}
/>
);
};
export { Toaster };

View File

@@ -42,10 +42,9 @@ export const apiClient = {
id: string, id: string,
updates: AccountUpdate, updates: AccountUpdate,
): Promise<{ id: string; display_name?: string }> => { ): Promise<{ id: string; display_name?: string }> => {
const response = await api.put<ApiResponse<{ id: string; display_name?: string }>>( const response = await api.put<
`/accounts/${id}`, ApiResponse<{ id: string; display_name?: string }>
updates, >(`/accounts/${id}`, updates);
);
return response.data.data; return response.data.data;
}, },