-
-
- Deploy now
-
-
- Read our docs
-
+ // Load transactions from localStorage on component mount
+ useEffect(() => {
+ const savedTransactions = localStorage.getItem('transactions');
+ if (savedTransactions) {
+ setTransactions(JSON.parse(savedTransactions));
+ }
+ }, []);
+
+ // Save transactions to localStorage whenever they change
+ useEffect(() => {
+ localStorage.setItem('transactions', JSON.stringify(transactions));
+ }, [transactions]);
+
+ const handleAddTransaction = (transaction: Transaction) => {
+ setTransactions([...transactions, transaction]);
+ };
+
+ const handleDeleteTransaction = (id: string) => {
+ setTransactions(transactions.filter(transaction => transaction.id !== id));
+ };
+
+ return (
+
+
+
Ausgaben Tracker
+
+
+
+
+
+
+
-
-
+
);
}
diff --git a/src/components/Summary.tsx b/src/components/Summary.tsx
new file mode 100644
index 0000000..fa2ea60
--- /dev/null
+++ b/src/components/Summary.tsx
@@ -0,0 +1,42 @@
+import { Transaction } from '@/types';
+
+interface SummaryProps {
+ transactions: Transaction[];
+}
+
+export default function Summary({ transactions }: SummaryProps) {
+ const totalIncome = transactions
+ .filter(t => t.type === 'income')
+ .reduce((sum, transaction) => sum + transaction.amount, 0);
+
+ const totalExpenses = transactions
+ .filter(t => t.type === 'expense')
+ .reduce((sum, transaction) => sum + transaction.amount, 0);
+
+ const balance = totalIncome - totalExpenses;
+
+ return (
+
+
Zusammenfassung
+
+
+
+
Einnahmen
+
+{totalIncome.toFixed(2)} €
+
+
+
+
Ausgaben
+
-{totalExpenses.toFixed(2)} €
+
+
+
+
Bilanz
+
= 0 ? 'text-green-600' : 'text-red-600'}`}>
+ {balance >= 0 ? '+' : ''}{balance.toFixed(2)} €
+
+
+
+
+ );
+}
diff --git a/src/components/TransactionForm.tsx b/src/components/TransactionForm.tsx
new file mode 100644
index 0000000..ba5270b
--- /dev/null
+++ b/src/components/TransactionForm.tsx
@@ -0,0 +1,104 @@
+import { useState } from 'react';
+import { Transaction } from '@/types';
+
+interface TransactionFormProps {
+ onAddTransaction: (transaction: Transaction) => void;
+}
+
+export default function TransactionForm({ onAddTransaction }: TransactionFormProps) {
+ const [description, setDescription] = useState('');
+ const [amount, setAmount] = useState('');
+ const [type, setType] = useState<'expense' | 'income'>('expense');
+
+ const handleSubmit = (e: React.FormEvent) => {
+ e.preventDefault();
+
+ if (!description || !amount) return;
+
+ const newTransaction: Transaction = {
+ id: Date.now().toString(),
+ description,
+ amount: parseFloat(amount),
+ type,
+ date: new Date().toISOString().split('T')[0]
+ };
+
+ onAddTransaction(newTransaction);
+
+ // Reset form
+ setDescription('');
+ setAmount('');
+ setType('expense');
+ };
+
+ return (
+
+ );
+}
diff --git a/src/components/TransactionList.tsx b/src/components/TransactionList.tsx
new file mode 100644
index 0000000..6190dd6
--- /dev/null
+++ b/src/components/TransactionList.tsx
@@ -0,0 +1,47 @@
+import { Transaction } from '@/types';
+
+interface TransactionListProps {
+ transactions: Transaction[];
+ onDeleteTransaction: (id: string) => void;
+}
+
+export default function TransactionList({ transactions, onDeleteTransaction }: TransactionListProps) {
+ if (transactions.length === 0) {
+ return (
+
+
Keine Transaktionen vorhanden
+
+ );
+ }
+
+ return (
+
+
Transaktionen
+
+ {transactions.map((transaction) => (
+ -
+
+
+
{transaction.description}
+
{transaction.date}
+
+
+
+ {transaction.type === 'income' ? '+' : '-'} {transaction.amount.toFixed(2)} €
+
+
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/src/types/index.ts b/src/types/index.ts
new file mode 100644
index 0000000..36f3438
--- /dev/null
+++ b/src/types/index.ts
@@ -0,0 +1,7 @@
+export interface Transaction {
+ id: string;
+ description: string;
+ amount: number;
+ type: 'expense' | 'income';
+ date: string;
+}