From a3274edbd0f457f061784b32d15b46a18d9ad517 Mon Sep 17 00:00:00 2001 From: Algroe User Date: Sat, 21 Mar 2026 13:21:23 +0800 Subject: [PATCH 1/2] Add transaction history page --- src/app/history/page.tsx | 75 +++++++++++++++++++++++++++++++++++++++ src/components/Navbar.tsx | 6 ++++ 2 files changed, 81 insertions(+) create mode 100644 src/app/history/page.tsx diff --git a/src/app/history/page.tsx b/src/app/history/page.tsx new file mode 100644 index 0000000..f73cb80 --- /dev/null +++ b/src/app/history/page.tsx @@ -0,0 +1,75 @@ +import React from 'react'; + +interface Transaction { + id: string; + date: string; + amount: number; + type: 'deposit' | 'withdrawal' | 'transfer'; + status: 'completed' | 'pending' | 'failed'; +} + +const transactions: Transaction[] = [ + { + id: '1', + date: '2026-03-20', + amount: 1000, + type: 'deposit', + status: 'completed' + }, + { + id: '2', + date: '2026-03-19', + amount: 500, + type: 'withdrawal', + status: 'completed' + }, + { + id: '3', + date: '2026-03-18', + amount: 200, + type: 'transfer', + status: 'pending' + } +]; + +const HistoryPage: React.FC = () => { + return ( +
+

Transaction History

+
+ + + + + + + + + + + + {transactions.map((transaction) => ( + + + + + + + + ))} + +
IDDateAmountTypeStatus
{transaction.id}{transaction.date}${transaction.amount.toFixed(2)} + + {transaction.type} + + + + {transaction.status} + +
+
+
+ ); +}; + +export default HistoryPage; \ No newline at end of file diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 2d673aa..9b1e5b3 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -25,6 +25,12 @@ export function Navbar() { > Create Group + + History + From f29da20e2a3135e4fbd208126f55935b27164a13 Mon Sep 17 00:00:00 2001 From: Algroe User Date: Sat, 21 Mar 2026 16:32:08 +0800 Subject: [PATCH 2/2] Add Toast Notification System - closes #260 --- github-bounty-hunter/frontend/src/App.tsx | 40 ++++++++++++++++++ .../frontend/src/components/Toast.tsx | 41 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 github-bounty-hunter/frontend/src/App.tsx create mode 100644 github-bounty-hunter/frontend/src/components/Toast.tsx diff --git a/github-bounty-hunter/frontend/src/App.tsx b/github-bounty-hunter/frontend/src/App.tsx new file mode 100644 index 0000000..253843c --- /dev/null +++ b/github-bounty-hunter/frontend/src/App.tsx @@ -0,0 +1,40 @@ +import React, { useState } from 'react'; +import Toast from './components/Toast'; + +const App: React.FC = () => { + const [toast, setToast] = useState<{ message: string; type: 'success' | 'error' | 'info' } | null>(null); + + const showToast = (message: string, type: 'success' | 'error' | 'info') => { + setToast({ message, type }); + setTimeout(() => setToast(null), 3000); + }; + + return ( +
+

Toast Notification System

+
+ + + +
+ {toast && } +
+ ); +}; + +export default App; \ No newline at end of file diff --git a/github-bounty-hunter/frontend/src/components/Toast.tsx b/github-bounty-hunter/frontend/src/components/Toast.tsx new file mode 100644 index 0000000..33dcb96 --- /dev/null +++ b/github-bounty-hunter/frontend/src/components/Toast.tsx @@ -0,0 +1,41 @@ +import React, { useEffect, useState } from 'react'; + +interface ToastProps { + message: string; + type?: 'success' | 'error' | 'info'; + duration?: number; +} + +const Toast: React.FC = ({ message, type = 'info', duration = 3000 }) => { + const [isVisible, setIsVisible] = useState(true); + + useEffect(() => { + const timer = setTimeout(() => { + setIsVisible(false); + }, duration); + + return () => clearTimeout(timer); + }, [duration]); + + if (!isVisible) return null; + + const getTypeClass = () => { + switch (type) { + case 'success': + return 'bg-green-500 text-white'; + case 'error': + return 'bg-red-500 text-white'; + case 'info': + default: + return 'bg-blue-500 text-white'; + } + }; + + return ( +
+ {message} +
+ ); +}; + +export default Toast; \ No newline at end of file