11"use client" ;
22
33import { useState , useEffect } from "react" ;
4- import { Copy , Check , LogOut , Moon , Sun , Bell } from "lucide-react" ;
4+ import { Copy , Check , LogOut , Moon , Sun , Bell , Globe } from "lucide-react" ;
55import { useWallet } from "@/context/wallet-context" ;
66import { useRouter } from "next/navigation" ;
77import { shortenPublicKey , formatNetwork } from "@/lib/wallet" ;
8+ import toast from "react-hot-toast" ;
9+
10+ type DisplayCurrency = "USD" | "XLM" | "USDC" ;
11+ type AmountFormat = "full" | "compact" ;
812
913export default function SettingsPage ( ) {
1014 const router = useRouter ( ) ;
1115 const { session, disconnect, isHydrated } = useWallet ( ) ;
12- const [ emailNotifications , setEmailNotifications ] = useState ( true ) ;
13- const [ theme , setTheme ] = useState < "light" | "dark" > ( ( ) => {
16+
17+ const [ browserPush , setBrowserPush ] = useState ( false ) ;
18+ const [ theme , setTheme ] = useState < "light" | "dark" | "system" > ( ( ) => {
1419 if ( typeof window !== "undefined" ) {
1520 const saved = localStorage . getItem ( "flowfi-theme" ) as
1621 | "light"
1722 | "dark"
23+ | "system"
1824 | null ;
1925 if ( saved ) {
2026 document . documentElement . classList . toggle ( "dark" , saved === "dark" ) ;
@@ -23,31 +29,66 @@ export default function SettingsPage() {
2329 }
2430 return "dark" ;
2531 } ) ;
32+
33+ const [ displayCurrency , setDisplayCurrency ] = useState < DisplayCurrency > ( ( ) => {
34+ if ( typeof window !== "undefined" ) {
35+ return ( localStorage . getItem ( "flowfi-currency" ) as DisplayCurrency ) || "USD" ;
36+ }
37+ return "USD" ;
38+ } ) ;
39+
40+ const [ amountFormat , setAmountFormat ] = useState < AmountFormat > ( ( ) => {
41+ if ( typeof window !== "undefined" ) {
42+ return ( localStorage . getItem ( "flowfi-amount-format" ) as AmountFormat ) || "full" ;
43+ }
44+ return "full" ;
45+ } ) ;
46+
2647 const [ copied , setCopied ] = useState ( false ) ;
2748
28- const toggleTheme = ( ) => {
29- const next = theme === "dark" ? "light" : "dark" ;
30- setTheme ( next ) ;
31- localStorage . setItem ( "flowfi-theme" , next ) ;
32- document . documentElement . classList . toggle (
33- "dark" ,
34- next === "dark"
35- ) ;
49+ const toggleTheme = ( newTheme : "light" | "dark" | "system" ) => {
50+ setTheme ( newTheme ) ;
51+ localStorage . setItem ( "flowfi-theme" , newTheme ) ;
52+ if ( newTheme === "system" ) {
53+ const prefersDark = window . matchMedia ( "(prefers-color-scheme: dark)" ) . matches ;
54+ document . documentElement . classList . toggle ( "dark" , prefersDark ) ;
55+ } else {
56+ document . documentElement . classList . toggle ( "dark" , newTheme === "dark" ) ;
57+ }
3658 } ;
3759
3860 const copyAddress = async ( ) => {
3961 if ( session ?. publicKey ) {
4062 await navigator . clipboard . writeText ( session . publicKey ) ;
4163 setCopied ( true ) ;
64+ toast . success ( "Address copied to clipboard" ) ;
4265 setTimeout ( ( ) => setCopied ( false ) , 1500 ) ;
4366 }
4467 } ;
4568
4669 const handleDisconnect = ( ) => {
4770 disconnect ( ) ;
71+ toast . success ( "Wallet disconnected" ) ;
4872 router . push ( "/" ) ;
4973 } ;
5074
75+ const handleBrowserPushToggle = async ( ) => {
76+ if ( ! browserPush ) {
77+ try {
78+ await Notification . requestPermission ( ) ;
79+ setBrowserPush ( Notification . permission === "granted" ) ;
80+ if ( Notification . permission === "granted" ) {
81+ toast . success ( "Browser notifications enabled" ) ;
82+ }
83+ } catch {
84+ toast . error ( "Failed to enable notifications" ) ;
85+ }
86+ } else {
87+ setBrowserPush ( false ) ;
88+ toast ( "Browser notifications disabled" ) ;
89+ }
90+ } ;
91+
5192 if ( ! isHydrated ) {
5293 return (
5394 < div className = "relative min-h-screen overflow-hidden bg-gradient-to-br from-zinc-950 via-zinc-900 to-black dark:from-white dark:via-gray-100 dark:to-gray-200 transition-colors flex items-center justify-center" >
@@ -68,42 +109,40 @@ export default function SettingsPage() {
68109
69110 < div >
70111 < h1 className = "text-3xl font-semibold tracking-tight text-white dark:text-black" >
71- Profile Settings
112+ Settings
72113 </ h1 >
73114 < p className = "text-sm opacity-60 mt-1" >
74- Manage your FlowFi experience
115+ Manage your FlowFi preferences
75116 </ p >
76117 </ div >
77118
78- { /* Email Notifications */ }
119+ { /* Browser Push Notifications */ }
79120 < div className = "flex items-center justify-between group" >
80121 < div className = "flex items-center gap-3" >
81122 < div className = "p-2 rounded-lg bg-purple-500/20 text-purple-400" >
82123 < Bell size = { 18 } />
83124 </ div >
84125 < div >
85126 < p className = "font-medium text-white dark:text-black" >
86- Email Notifications
127+ Browser Notifications
87128 </ p >
88129 < p className = "text-sm opacity-60" >
89- Get notified about activity
130+ Get notified about stream activity
90131 </ p >
91132 </ div >
92133 </ div >
93134
94135 < button
95- onClick = { ( ) =>
96- setEmailNotifications ( ! emailNotifications )
97- }
136+ onClick = { handleBrowserPushToggle }
98137 className = { `relative w-14 h-7 rounded-full transition-all duration-300 ${
99- emailNotifications
138+ browserPush
100139 ? "bg-gradient-to-r from-purple-500 to-blue-500"
101140 : "bg-zinc-600"
102141 } `}
103142 >
104143 < span
105144 className = { `absolute top-1 left-1 w-5 h-5 bg-white rounded-full shadow-md transform transition duration-300 ${
106- emailNotifications
145+ browserPush
107146 ? "translate-x-7"
108147 : "translate-x-0"
109148 } `}
@@ -112,27 +151,94 @@ export default function SettingsPage() {
112151 </ div >
113152
114153 { /* Theme Toggle */ }
115- < div className = "flex items-center justify-between " >
154+ < div className = "space-y-4 " >
116155 < div className = "flex items-center gap-3" >
117156 < div className = "p-2 rounded-lg bg-blue-500/20 text-blue-400" >
118- { theme === "dark" ? < Moon size = { 18 } /> : < Sun size = { 18 } /> }
157+ { theme === "dark" ? < Moon size = { 18 } /> : theme === "light" ? < Sun size = { 18 } /> : < Globe size = { 18 } /> }
119158 </ div >
120159 < div >
121160 < p className = "font-medium text-white dark:text-black" >
122161 Appearance
123162 </ p >
124163 < p className = "text-sm opacity-60" >
125- Toggle dark & light mode
164+ Choose your theme preference
126165 </ p >
127166 </ div >
128167 </ div >
129168
130- < button
131- onClick = { toggleTheme }
132- className = "px-4 py-2 text-sm rounded-xl border border-white/10 dark:border-black/10 hover:scale-105 transition-transform text-white dark:text-black"
133- >
134- { theme === "dark" ? "Light Mode" : "Dark Mode" }
135- </ button >
169+ < div className = "flex gap-2" >
170+ { ( [ "light" , "dark" , "system" ] as const ) . map ( ( t ) => (
171+ < button
172+ key = { t }
173+ onClick = { ( ) => toggleTheme ( t ) }
174+ className = { `px-4 py-2 text-sm rounded-xl border transition-all ${
175+ theme === t
176+ ? "border-purple-500 bg-purple-500/20 text-white"
177+ : "border-white/10 dark:border-black/10 text-white/60 dark:text-black/60 hover:border-white/20"
178+ } `}
179+ >
180+ { t . charAt ( 0 ) . toUpperCase ( ) + t . slice ( 1 ) }
181+ </ button >
182+ ) ) }
183+ </ div >
184+ </ div >
185+
186+ { /* Display Preferences */ }
187+ < div className = "space-y-4" >
188+ < div className = "flex items-center gap-3" >
189+ < div className = "p-2 rounded-lg bg-green-500/20 text-green-400" >
190+ < Globe size = { 18 } />
191+ </ div >
192+ < div >
193+ < p className = "font-medium text-white dark:text-black" >
194+ Display Preferences
195+ </ p >
196+ < p className = "text-sm opacity-60" >
197+ Customize how amounts are displayed
198+ </ p >
199+ </ div >
200+ </ div >
201+
202+ < div className = "space-y-3 pl-12" >
203+ < div >
204+ < label className = "text-sm text-white/60 dark:text-black/60" > Default Token</ label >
205+ < select
206+ value = { displayCurrency }
207+ onChange = { ( e ) => {
208+ const val = e . target . value as DisplayCurrency ;
209+ setDisplayCurrency ( val ) ;
210+ localStorage . setItem ( "flowfi-currency" , val ) ;
211+ } }
212+ className = "mt-1 block w-full px-3 py-2 rounded-lg bg-black/40 dark:bg-white/40 border border-white/10 dark:border-black/10 text-white dark:text-black text-sm"
213+ >
214+ < option value = "USD" > USD</ option >
215+ < option value = "XLM" > XLM</ option >
216+ < option value = "USDC" > USDC</ option >
217+ </ select >
218+ </ div >
219+
220+ < div >
221+ < label className = "text-sm text-white/60 dark:text-black/60" > Amount Format</ label >
222+ < div className = "flex gap-2 mt-1" >
223+ { ( [ "full" , "compact" ] as const ) . map ( ( fmt ) => (
224+ < button
225+ key = { fmt }
226+ onClick = { ( ) => {
227+ setAmountFormat ( fmt ) ;
228+ localStorage . setItem ( "flowfi-amount-format" , fmt ) ;
229+ } }
230+ className = { `px-3 py-1.5 text-xs rounded-lg border transition-all ${
231+ amountFormat === fmt
232+ ? "border-blue-500 bg-blue-500/20 text-white"
233+ : "border-white/10 text-white/60 hover:border-white/20"
234+ } `}
235+ >
236+ { fmt === "full" ? "Full (1.0000000)" : "Compact (1.0)" }
237+ </ button >
238+ ) ) }
239+ </ div >
240+ </ div >
241+ </ div >
136242 </ div >
137243
138244 { /* Wallet Section */ }
@@ -202,4 +308,4 @@ export default function SettingsPage() {
202308 </ div >
203309 </ div >
204310 ) ;
205- }
311+ }
0 commit comments