diff --git a/frontend/src/components/AccountsOverview.tsx b/frontend/src/components/AccountsOverview.tsx index 8df1311..718a7f3 100644 --- a/frontend/src/components/AccountsOverview.tsx +++ b/frontend/src/components/AccountsOverview.tsx @@ -1,4 +1,5 @@ -import { useQuery } from "@tanstack/react-query"; +import { useState } from "react"; +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { CreditCard, TrendingUp, @@ -6,6 +7,9 @@ import { Building2, RefreshCw, AlertCircle, + Edit2, + Check, + X, } from "lucide-react"; import { apiClient } from "../lib/api"; import { formatCurrency, formatDate } from "../lib/utils"; @@ -28,6 +32,43 @@ export default function AccountsOverview() { queryFn: () => apiClient.getBalances(), }); + const [editingAccountId, setEditingAccountId] = useState(null); + const [editingName, setEditingName] = useState(""); + + const queryClient = useQueryClient(); + + const updateAccountMutation = useMutation({ + mutationFn: ({ id, name }: { id: string; name: string }) => + apiClient.updateAccount(id, { name }), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["accounts"] }); + setEditingAccountId(null); + setEditingName(""); + }, + onError: (error) => { + console.error("Failed to update account:", error); + }, + }); + + const handleEditStart = (account: Account) => { + setEditingAccountId(account.id); + setEditingName(account.name || ""); + }; + + const handleEditSave = () => { + if (editingAccountId && editingName.trim()) { + updateAccountMutation.mutate({ + id: editingAccountId, + name: editingName.trim(), + }); + } + }; + + const handleEditCancel = () => { + setEditingAccountId(null); + setEditingName(""); + }; + if (accountsLoading) { return (
@@ -167,19 +208,69 @@ export default function AccountsOverview() {
-
-

- {account.name || "Unnamed Account"} -

-

- {account.institution_id} • {account.status} -

- {account.iban && ( -

- IBAN: {account.iban} -

- )} -
+
+ {editingAccountId === account.id ? ( +
+
+ setEditingName(e.target.value)} + className="flex-1 px-3 py-1 text-lg font-medium border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + placeholder="Account name" + name="search" + autoComplete="off" + onKeyDown={(e) => { + if (e.key === "Enter") handleEditSave(); + if (e.key === "Escape") handleEditCancel(); + }} + autoFocus + /> + + +
+

+ {account.institution_id} • {account.status} +

+
+ ) : ( +
+
+

+ {account.name || "Unnamed Account"} +

+ +
+

+ {account.institution_id} • {account.status} +

+ {account.iban && ( +

+ IBAN: {account.iban} +

+ )} +
+ )} +
diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 1818cb0..36527e6 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -9,6 +9,7 @@ import type { NotificationService, NotificationServicesResponse, HealthData, + AccountUpdate, } from "../types/api"; // Use VITE_API_URL for development, relative URLs for production @@ -34,6 +35,12 @@ export const apiClient = { return response.data.data; }, + // Update account details + updateAccount: async (id: string, updates: AccountUpdate): Promise<{ id: string; name?: string }> => { + const response = await api.put>(`/accounts/${id}`, updates); + return response.data.data; + }, + // Get all balances getBalances: async (): Promise => { const response = await api.get>("/balances"); diff --git a/frontend/src/types/api.ts b/frontend/src/types/api.ts index 4e9f230..daa157c 100644 --- a/frontend/src/types/api.ts +++ b/frontend/src/types/api.ts @@ -17,6 +17,10 @@ export interface Account { balances: AccountBalance[]; } +export interface AccountUpdate { + name?: string; +} + export interface RawTransactionData { transactionId?: string; bookingDate?: string;