Skip to content

Commit 19b06e7

Browse files
authored
Merge pull request #70 from Benedict315/main
feat: refactor Home component and add mock data for initial messages …
2 parents 138054e + 90e6532 commit 19b06e7

10 files changed

Lines changed: 119 additions & 38 deletions

File tree

frontend/package-lock.json

Lines changed: 28 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"lucide-react": "^0.577.0",
1313
"next": "16.1.6",
1414
"react": "19.2.3",
15-
"react-dom": "19.2.3"
15+
"react-dom": "19.2.3",
16+
"react-hot-toast": "^2.6.0"
1617
},
1718
"devDependencies": {
1819
"@types/node": "^20",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { WalletModal } from "./WalletModal";
2+
3+
interface WalletModalTestProps {
4+
isOpen: boolean;
5+
onClose: () => void;
6+
}
7+
8+
export function WalletModalTest({
9+
isOpen,
10+
onClose,
11+
}: WalletModalTestProps) {
12+
return <WalletModal isOpen={isOpen} onClose={onClose} />;
13+
}

frontend/src/app/layout.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Metadata } from 'next';
22
import './globals.css';
33
import { WalletProvider } from './components/WalletContext';
44
import { ErrorBoundary } from './components/ErrorBoundary';
5+
import { Toaster } from 'react-hot-toast';
56

67
export const metadata: Metadata = {
78
title: 'Smasage | AI Portfolio Manager',
@@ -24,6 +25,18 @@ export default function RootLayout({
2425
{children}
2526
</ErrorBoundary>
2627
</WalletProvider>
28+
<Toaster
29+
position="top-right"
30+
toastOptions={{
31+
duration: 4000,
32+
style: {
33+
background: 'rgba(255, 255, 255, 0.95)',
34+
color: '#000',
35+
border: '1px solid rgba(255, 255, 255, 0.2)',
36+
backdropFilter: 'blur(10px)',
37+
},
38+
}}
39+
/>
2740
</body>
2841
</html>
2942
);

frontend/src/app/page.tsx

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ import {
2626
GoalTrackerSkeleton,
2727
PortfolioChartSkeleton,
2828
} from "./components/SkeletonLoader";
29-
import { WalletModal } from "./components/WalletModal";
29+
import { WalletModalTest } from "./components/WalletModalTest";
3030
import { ChatInterface, type ChatMessage } from "./components/ChatInterface";
31+
import { goalData, initialMessages } from "../config/mockData";
32+
import toast from 'react-hot-toast';
3133
import { GoalTracker } from "./components/GoalTracker";
3234
import { GlassPanel } from "./components/GlassPanel";
3335

@@ -40,13 +42,7 @@ export default function Home() {
4042
isConnecting
4143
} = useFreighter();
4244

43-
const [messages, setMessages] = useState<ChatMessage[]>([
44-
{
45-
id: 1,
46-
sender: "agent",
47-
text: "Welcome to Smasage! 👋 I'm OpenClaw, your personal AI savings assistant natively built on Stellar. What financial goal can we crush today?",
48-
},
49-
]);
45+
const [messages, setMessages] = useState<ChatMessage[]>(initialMessages);
5046
const [isTyping, setIsTyping] = useState(false);
5147

5248
const [allocations, setAllocations] = useState<AssetAllocation[]>(
@@ -56,15 +52,6 @@ export default function Home() {
5652
const [wsConnected, setWsConnected] = useState(false);
5753
const [isLoading, setIsLoading] = useState(true);
5854

59-
// Goal data (Memoized to avoid unnecessary effect triggers)
60-
const goalData = useMemo<GoalData>(() => ({
61-
currentBalance: 12450,
62-
targetAmount: 18000,
63-
targetDate: "2026-08-01",
64-
monthlyContribution: 500,
65-
expectedAPY: 8.5,
66-
}), []);
67-
6855
// Calculate goal status and progress using useMemo to avoid cascading renders
6956
const { goalStatus, progress } = useMemo(() => {
7057
const result = evaluateGoalStatus(goalData);
@@ -94,6 +81,13 @@ export default function Home() {
9481
setMessages((prev: ChatMessage[]) => [...prev, agentMsg]);
9582
console.log("[App] Agent message received", text);
9683

84+
// Show toast for proactive messages
85+
if (proactive) {
86+
toast('💡 New suggestion from OpenClaw', {
87+
duration: 5000,
88+
});
89+
}
90+
9791
// Parse allocations if present
9892
const parsedAllocations = parseAllocationsFromMessage(text);
9993
if (parsedAllocations) {
@@ -103,6 +97,7 @@ export default function Home() {
10397
},
10498
onError: (error) => {
10599
console.error("[App] WebSocket error:", error);
100+
toast.error('Failed to connect to notification service');
106101
},
107102
enabled: true,
108103
});
@@ -169,7 +164,7 @@ export default function Home() {
169164
/>
170165
</DashboardHeader>
171166

172-
<WalletModal
167+
<WalletModalTest
173168
isOpen={showInstallModal}
174169
onClose={() => setShowInstallModal(false)}
175170
/>

frontend/src/config/mockData.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type { ChatMessage } from '../app/components/ChatInterface';
2+
import type { AssetAllocation } from '../utils/chartUtils';
3+
import type { GoalData } from '../utils/goalProjection';
4+
5+
export const goalData: GoalData = {
6+
currentBalance: 12450,
7+
targetAmount: 18000,
8+
targetDate: '2026-08-01',
9+
monthlyContribution: 500,
10+
expectedAPY: 8.5,
11+
};
12+
13+
export const initialMessages: ChatMessage[] = [
14+
{
15+
id: 1,
16+
sender: 'agent',
17+
text: 'Welcome to Smasage! 👋 I\'m OpenClaw, your personal AI savings assistant natively built on Stellar. What financial goal can we crush today?',
18+
},
19+
];
20+
21+
export const defaultAllocations: AssetAllocation[] = [
22+
{
23+
name: 'Blend Protocol Yield (USDC)',
24+
percentage: 60,
25+
color: '#8b5cf6',
26+
},
27+
{
28+
name: 'Soroswap LP (XLM/USDC)',
29+
percentage: 30,
30+
color: '#06b6d4',
31+
},
32+
{
33+
name: 'Stellar Anchored Gold (XAUT)',
34+
percentage: 10,
35+
color: '#f59e0b',
36+
},
37+
];

frontend/src/hooks/useFreighter.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useState, useCallback, useEffect } from "react";
22
import { useWallet } from "../app/components/WalletContext";
3+
import toast from 'react-hot-toast';
34

45
/**
56
* Custom hook to manage Freighter wallet interactions.
@@ -45,6 +46,9 @@ export function useFreighter() {
4546

4647
if (!api) {
4748
setShowInstallModal(true);
49+
toast.error('Freighter wallet not detected. Please install the extension and refresh the page.', {
50+
duration: 6000,
51+
});
4852
return null;
4953
}
5054

@@ -55,9 +59,11 @@ export function useFreighter() {
5559
try {
5660
const key = await api.getPublicKey();
5761
setPublicKey(key);
62+
toast.success('Wallet connected successfully! 🎉');
5863
return key;
5964
} catch (error) {
6065
console.error("[useFreighter] Connection failed:", error);
66+
toast.error('Failed to connect wallet. Please try again.');
6167
return null;
6268
} finally {
6369
setIsConnecting(false);
@@ -69,6 +75,7 @@ export function useFreighter() {
6975
*/
7076
const disconnect = useCallback(() => {
7177
setPublicKey(null);
78+
toast('Wallet disconnected');
7279
}, [setPublicKey]);
7380

7481
return {

frontend/src/hooks/useNotifications.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
WS_MAX_RECONNECT_DELAY_MS,
1212
} from "../config/constants";
1313
import type { IncomingNotification, GoalPayload } from "../types/websocket";
14+
import toast from 'react-hot-toast';
1415

1516
// Re-export so existing imports from this module continue to work.
1617
export type { IncomingNotification } from "../types/websocket";
@@ -45,6 +46,7 @@ export function useNotifications(options: UseNotificationsOptions) {
4546
console.log("[WS] Connected");
4647
reconnectAttemptsRef.current = 0;
4748
setIsConnected(true);
49+
toast.success('Connected to notification service');
4850

4951
// Send initial registration
5052
ws.send(
@@ -69,13 +71,15 @@ export function useNotifications(options: UseNotificationsOptions) {
6971
ws.onerror = (event) => {
7072
const error = new Error("WebSocket error");
7173
console.error("[WS] Error:", error, event);
74+
toast.error('Connection to notification service failed');
7275
onError?.(error);
7376
};
7477

7578
ws.onclose = () => {
7679
console.log("[WS] Disconnected");
7780
wsRef.current = null;
7881
setIsConnected(false);
82+
toast.error('Disconnected from notification service');
7983

8084
// Attempt reconnection with exponential backoff
8185
if (reconnectAttemptsRef.current < maxReconnectAttempts) {

frontend/src/utils/allocationParser.ts

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
import type { AssetAllocation } from "./chartUtils";
7+
import { defaultAllocations } from "../config/mockData";
78

89
// Color scheme matching the theme
910
const ALLOCATION_COLORS = {
@@ -93,21 +94,5 @@ function getColorForAsset(assetName: string): string {
9394
* Get default allocations
9495
*/
9596
export function getDefaultAllocations(): AssetAllocation[] {
96-
return [
97-
{
98-
name: "Blend Protocol Yield (USDC)",
99-
percentage: 60,
100-
color: ALLOCATION_COLORS.blend,
101-
},
102-
{
103-
name: "Soroswap LP (XLM/USDC)",
104-
percentage: 30,
105-
color: ALLOCATION_COLORS.soroswap,
106-
},
107-
{
108-
name: "Stellar Anchored Gold (XAUT)",
109-
percentage: 10,
110-
color: ALLOCATION_COLORS.gold,
111-
},
112-
];
97+
return defaultAllocations;
11398
}

temp.ps1

76 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)