diff --git a/astro.config.mjs b/astro.config.mjs
index 59b224b..b338785 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -15,6 +15,15 @@ export default defineConfig({
vite: {
resolve: {
alias: {
+ '@': '/src',
+ '@components': '/src/components',
+ '@layouts': '/src/layouts',
+ '@data': '/src/data',
+ '@pages': '/src/pages',
+ '@styles': '/src/styles',
+ '@stores': '/src/stores',
+ '@utils': '/src/utils',
+ '@types': '/src/types.ts',
// Use the browser version of react-dom/server for client-side rendering
'react-dom/server.browser': 'react-dom/cjs/react-dom-server.browser.production.min.js',
},
diff --git a/src/components/AccountSummary.tsx b/src/components/AccountSummary.tsx
index 3664471..814f1d4 100644
--- a/src/components/AccountSummary.tsx
+++ b/src/components/AccountSummary.tsx
@@ -1,7 +1,7 @@
import { useStore } from '@nanostores/react';
import { currentAccountId as currentAccountIdStore, refreshKey } from '@stores/transactionStore';
import type { Account } from '@types';
-import { formatCurrency } from '@utils/formatters';
+import { formatCurrency } from '@utils';
import { useEffect, useState } from 'react';
export default function AccountSummary() {
diff --git a/src/components/MainContent.astro b/src/components/MainContent.astro
index c9d20f8..7770e81 100644
--- a/src/components/MainContent.astro
+++ b/src/components/MainContent.astro
@@ -1,19 +1,22 @@
---
-import type { Account } from '@types';
+import type { Account, Transaction } from "@types";
+import TransactionTable from "./TransactionTable.astro";
interface Props {
account: Account;
+ transactions: Transaction[];
}
-const { account } = Astro.props;
+const { account, transactions } = Astro.props;
---
Transactions for {account.name} (***{account.accountNumber.slice(-3)})
+ >{account.name} (***{account.accountNumber.slice(-3)})
-
+
diff --git a/src/components/Sidebar.astro b/src/components/Sidebar.astro
index 2dc8fd3..6dcbd9c 100644
--- a/src/components/Sidebar.astro
+++ b/src/components/Sidebar.astro
@@ -1,9 +1,11 @@
---
-import type { Account } from '@types';
+import type { Account } from "@types";
+import AddTransactionForm from "./AddTransactionForm";
+import AccountSummary from "./AccountSummary";
interface Props {
- accounts: Account[];
- initialAccount: Account;
+ accounts: Account[];
+ initialAccount: Account;
}
const { accounts, initialAccount } = Astro.props;
diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro
index e6d1e2b..a5d863c 100644
--- a/src/layouts/BaseLayout.astro
+++ b/src/layouts/BaseLayout.astro
@@ -1,6 +1,6 @@
---
-interface Props {
- title: string;
+export interface Props {
+ title: string;
}
// TODO: Accessibility Improvements
diff --git a/src/pages/api/accounts/index.ts b/src/pages/api/accounts/index.ts
index bd261d2..9b8e2b0 100644
--- a/src/pages/api/accounts/index.ts
+++ b/src/pages/api/accounts/index.ts
@@ -2,11 +2,13 @@ import { AccountStatus, AccountType, accountService } from '@data/db.service';
import type { Account } from '@types';
import type { APIRoute } from 'astro';
-export const GET: APIRoute = async () => {
+export const GET: APIRoute = async ({ params, request }) => {
try {
+ console.log('GET /api/accounts - Fetching all accounts');
const accounts = await accountService.getAll();
+ console.log('GET /api/accounts - Found accounts:', accounts?.length ?? 0);
- return new Response(JSON.stringify(accounts), {
+ return new Response(JSON.stringify(accounts || []), {
status: 200,
headers: {
'Content-Type': 'application/json',
@@ -14,12 +16,19 @@ export const GET: APIRoute = async () => {
});
} catch (error) {
console.error('Error fetching accounts:', error);
- return new Response(JSON.stringify({ error: 'Failed to fetch accounts' }), {
- status: 500,
- headers: {
- 'Content-Type': 'application/json',
+ // Always return a proper JSON response, even in error cases
+ return new Response(
+ JSON.stringify({
+ error: 'Failed to fetch accounts',
+ details: error instanceof Error ? error.message : 'Unknown error',
+ }),
+ {
+ status: 500,
+ headers: {
+ 'Content-Type': 'application/json',
+ },
},
- });
+ );
}
};
diff --git a/src/pages/index.astro b/src/pages/index.astro
index cb4bddb..ddb6394 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -1,36 +1,52 @@
---
-import type { Account, Transaction } from '@types';
+import BaseLayout from "@layouts/BaseLayout.astro";
+import MainContent from "@components/MainContent.astro";
+import Sidebar from "@components/Sidebar.astro";
+import AddTransactionForm from "@components/AddTransactionForm";
+import type { Account, Transaction } from "@types";
-// Get the base URL from the incoming request
-const baseUrl = new URL(Astro.request.url).origin;
-
-// Fetch accounts from API using absolute URL constructed from the request
-const accountsResponse = await fetch(`${baseUrl}/api/accounts`);
-const accounts: Account[] = await accountsResponse.json();
+// Create an instance of Astro's built-in fetch which handles SSR correctly
+let accounts: Account[] = [];
+try {
+ const accountsResponse = await fetch(new URL("/api/accounts", Astro.url));
+ if (!accountsResponse.ok) {
+ const error = await accountsResponse.text();
+ console.error("Failed to fetch accounts:", error);
+ // Continue with empty accounts array
+ } else {
+ accounts = await accountsResponse.json();
+ }
+} catch (error) {
+ console.error("Error fetching accounts:", error);
+ // Continue with empty accounts array
+}
// Initialize with first account or empty account if none exist
const initialAccount: Account = accounts[0] || {
- id: '',
- name: 'No accounts available',
- accountNumber: '000000',
- balance: 0,
- bankName: '',
+ id: "",
+ name: "No accounts available",
+ accountNumber: "000000",
+ balance: 0,
+ bankName: "",
};
-// Fetch initial transactions if we have an account, using absolute URL
+// Fetch initial transactions if we have an account
let initialTransactions: Transaction[] = [];
if (initialAccount.id) {
- const transactionsResponse = await fetch(
- `${baseUrl}/api/accounts/${initialAccount.id}/transactions`,
- );
- initialTransactions = await transactionsResponse.json();
+ const transactionsResponse = await fetch(
+ new URL(`/api/accounts/${initialAccount.id}/transactions`, Astro.url),
+ );
+ initialTransactions = await transactionsResponse.json();
}
---
-
+
@@ -56,20 +72,24 @@ if (initialAccount.id) {
);
// --- DOM Elements ---
- const accountSelect = document.getElementById("account-select");
+ const accountSelect = document.getElementById(
+ "account-select",
+ ) as HTMLSelectElement | null;
const currentAccountNameSpan = document.getElementById(
"current-account-name",
- );
+ ) as HTMLSpanElement | null;
const addTransactionSection = document.getElementById(
"add-transaction-section",
- );
- const toggleAddTxnBtn = document.getElementById("toggle-add-txn-btn");
+ ) as HTMLElement | null;
+ const toggleAddTxnBtn = document.getElementById(
+ "toggle-add-txn-btn",
+ ) as HTMLButtonElement | null;
console.log("Initial setup - Account:", initialAccountData);
console.log("Initial setup - Transactions:", initialTransactionsData);
// --- Helper Functions ---
- async function fetchAccountDetails(accountId) {
+ async function fetchAccountDetails(accountId: string) {
console.log("Fetching details for account:", accountId);
try {
const response = await fetch(`/api/accounts/${accountId}`);
@@ -83,7 +103,7 @@ if (initialAccount.id) {
}
// --- Update UI Function ---
- async function updateUIForAccount(accountId) {
+ async function updateUIForAccount(accountId: string) {
console.log("Updating UI for account:", accountId);
// Update the store with the current account ID
@@ -118,7 +138,7 @@ if (initialAccount.id) {
}
// --- Transaction Actions ---
- async function handleEditTransaction(txnId) {
+ async function handleEditTransaction(txnId: string) {
console.log("Edit transaction requested:", txnId);
try {
const accountId = currentAccountId.get();
@@ -133,7 +153,9 @@ if (initialAccount.id) {
if (!response.ok)
throw new Error("Failed to fetch transactions for edit");
const transactions = await response.json();
- const transaction = transactions.find((t) => t.id === txnId);
+ const transaction = transactions.find(
+ (t: { id: string }) => t.id === txnId,
+ );
if (!transaction) {
throw new Error("Transaction not found for editing");
@@ -164,18 +186,18 @@ if (initialAccount.id) {
// --- Event Listeners ---
if (accountSelect) {
- accountSelect.addEventListener("change", (event) => {
- const target = event.target;
- if (target && target.value) {
+ accountSelect.addEventListener("change", (event: Event) => {
+ const target = event.target as HTMLSelectElement;
+ if (target?.value) {
updateUIForAccount(target.value);
}
});
}
- document.addEventListener("click", (event) => {
- const target = event.target;
- if (target && target.classList.contains("edit-btn")) {
- const row = target.closest("[data-txn-id]");
+ document.addEventListener("click", (event: Event) => {
+ const target = event.target as HTMLElement;
+ if (target?.classList?.contains("edit-btn")) {
+ const row = target.closest("[data-txn-id]") as HTMLElement;
if (row) {
const txnId = row.dataset.txnId;
if (txnId) handleEditTransaction(txnId);
diff --git a/tsconfig.json b/tsconfig.json
index 8130b47..f546930 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -14,7 +14,7 @@
"@pages/*": ["src/pages/*"],
"@styles/*": ["src/styles/*"],
"@stores/*": ["src/stores/*"],
- "@utils/*": ["src/utils.ts"],
+ "@utils": ["src/utils"],
"@types": ["src/types.ts"]
}
}