@@ -6,12 +6,7 @@ import { useToast } from "@/hooks/use-toast";
66import useUser from "@/hooks/useUser" ;
77
88import { Button } from "@/components/ui/button" ;
9- import {
10- Card ,
11- CardContent ,
12- CardHeader ,
13- CardTitle ,
14- } from "@/components/ui/card" ;
9+ import { Card , CardContent , CardHeader , CardTitle } from "@/components/ui/card" ;
1510import {
1611 Dialog ,
1712 DialogContent ,
@@ -24,20 +19,22 @@ import GlassMorphismPageWrapper from "@/components/pages/homepage/wallets/new-wa
2419import WalletInfoCard from "./WalletInfoCard" ;
2520import JoinAsSignerCard from "./JoinAsSignerCard" ;
2621import ManageSignerCard from "./ManageSignerCard" ;
22+ import { serializeRewardAddress , deserializeAddress } from "@meshsdk/core" ;
2723
2824export default function PageNewWalletInvite ( ) {
2925 const router = useRouter ( ) ;
3026 const [ loading , setLoading ] = useState < boolean > ( false ) ;
3127 const [ signersDescription , setSignerDescription ] = useState < string > ( "" ) ;
3228 const [ deleteDialogOpen , setDeleteDialogOpen ] = useState ( false ) ;
3329 const [ localSignerName , setLocalSignerName ] = useState < string > ( "" ) ;
30+ const [ showNotFound , setShowNotFound ] = useState ( false ) ;
3431 const userAddress = useUserStore ( ( state ) => state . userAddress ) ;
3532 const { user } = useUser ( ) ;
3633 const { toast } = useToast ( ) ;
3734
3835 const pathIsNewWallet = router . pathname == "/wallets/invite/[id]" ;
3936 const newWalletId = pathIsNewWallet ? ( router . query . id as string ) : undefined ;
40-
37+
4138 const utils = api . useUtils ( ) ;
4239
4340 const { data : newWallet } = api . wallet . getNewWallet . useQuery (
@@ -46,15 +43,28 @@ export default function PageNewWalletInvite() {
4643 enabled : pathIsNewWallet && newWalletId !== undefined ,
4744 } ,
4845 ) ;
49-
46+
47+ useEffect ( ( ) => {
48+ if ( ! newWallet ) {
49+ setShowNotFound ( false ) ;
50+ const timer = setTimeout ( ( ) => {
51+ setShowNotFound ( true ) ;
52+ } , 5000 ) ;
53+ return ( ) => clearTimeout ( timer ) ;
54+ }
55+ } , [ newWallet ] ) ;
56+
5057 // Calculate user role once (after newWallet is loaded)
5158 const isOwner = newWallet ?. ownerAddress === userAddress ;
52- const isAlreadySigner = newWallet ?. signersAddresses . includes ( userAddress || "" ) || false ;
59+ const isAlreadySigner =
60+ newWallet ?. signersAddresses . includes ( userAddress || "" ) || false ;
5361
5462 // Set initial signer name when wallet data loads
5563 useEffect ( ( ) => {
5664 if ( newWallet && userAddress ) {
57- const signerIndex = newWallet . signersAddresses . findIndex ( addr => addr === userAddress ) ;
65+ const signerIndex = newWallet . signersAddresses . findIndex (
66+ ( addr ) => addr === userAddress ,
67+ ) ;
5868 if ( signerIndex !== - 1 ) {
5969 setLocalSignerName ( newWallet . signersDescriptions [ signerIndex ] || "" ) ;
6070 }
@@ -85,15 +95,17 @@ export default function PageNewWalletInvite() {
8595 } ,
8696 } ) ;
8797
88- const { mutate : updateNewWalletSignersDescriptions , isLoading : isUpdatingName } =
98+ const updateNewWalletSignersDescriptionsMutation =
8999 api . wallet . updateNewWalletSignersDescriptions . useMutation ( {
90100 onSuccess : async ( data , variables ) => {
91101 // Update local state with new name
92- const userIndex = newWallet ?. signersAddresses . findIndex ( ( item ) => item === userAddress ) ;
102+ const userIndex = newWallet ?. signersAddresses . findIndex (
103+ ( item ) => item === userAddress ,
104+ ) ;
93105 if ( userIndex !== - 1 && userIndex !== undefined ) {
94106 setLocalSignerName ( variables . signersDescriptions [ userIndex ] || "" ) ;
95107 }
96-
108+
97109 toast ( {
98110 title : "Name Updated" ,
99111 description : "Your name has been updated" ,
@@ -109,11 +121,17 @@ export default function PageNewWalletInvite() {
109121 } ) ;
110122 } ,
111123 } ) ;
124+ const updateNewWalletSignersDescriptions =
125+ updateNewWalletSignersDescriptionsMutation . mutate ;
126+ const isUpdatingName =
127+ updateNewWalletSignersDescriptionsMutation . status === "pending" ;
112128
113129 async function addSigner ( ) {
114130 if ( newWallet === undefined || newWallet === null )
115131 throw new Error ( "Wallet invite is undefined" ) ;
116132 if ( userAddress === undefined ) throw new Error ( "User address is undefined" ) ;
133+ const dsAddr = deserializeAddress ( userAddress ) ;
134+ console . log ( "User stake address:" , dsAddr ) ;
117135 if ( ! user ?. stakeAddress ) throw new Error ( "User stake address is undefined" ) ;
118136
119137 setLoading ( true ) ;
@@ -134,7 +152,9 @@ export default function PageNewWalletInvite() {
134152 throw new Error ( "Wallet invite is undefined" ) ;
135153 if ( userAddress === undefined ) throw new Error ( "User address is undefined" ) ;
136154
137- const userIndex = newWallet . signersAddresses . findIndex ( ( item ) => item === userAddress ) ;
155+ const userIndex = newWallet . signersAddresses . findIndex (
156+ ( item ) => item === userAddress ,
157+ ) ;
138158 if ( userIndex === - 1 ) throw new Error ( "User index is not found" ) ;
139159
140160 const updatedDescriptions = [ ...newWallet . signersDescriptions ] ;
@@ -155,18 +175,26 @@ export default function PageNewWalletInvite() {
155175 throw new Error ( "Wallet invite is undefined" ) ;
156176 if ( userAddress === undefined ) throw new Error ( "User address is undefined" ) ;
157177
158- const userIndex = newWallet . signersAddresses . findIndex ( ( item ) => item === userAddress ) ;
178+ const userIndex = newWallet . signersAddresses . findIndex (
179+ ( item ) => item === userAddress ,
180+ ) ;
159181 if ( userIndex === - 1 ) throw new Error ( "User index is not found" ) ;
160182
161183 setLoading ( true ) ;
162184 setDeleteDialogOpen ( false ) ;
163-
185+
164186 // Clear local name when removing - user is completely out
165187 setLocalSignerName ( "" ) ;
166188
167- const updatedAddresses = newWallet . signersAddresses . filter ( ( _ , i ) => i !== userIndex ) ;
168- const updatedStakeKeys = newWallet . signersStakeKeys . filter ( ( _ , i ) => i !== userIndex ) ;
169- const updatedDescriptions = newWallet . signersDescriptions . filter ( ( _ , i ) => i !== userIndex ) ;
189+ const updatedAddresses = newWallet . signersAddresses . filter (
190+ ( _ , i ) => i !== userIndex ,
191+ ) ;
192+ const updatedStakeKeys = newWallet . signersStakeKeys . filter (
193+ ( _ , i ) => i !== userIndex ,
194+ ) ;
195+ const updatedDescriptions = newWallet . signersDescriptions . filter (
196+ ( _ , i ) => i !== userIndex ,
197+ ) ;
170198
171199 updateNewWalletSigners ( {
172200 walletId : newWalletId ! ,
@@ -175,114 +203,136 @@ export default function PageNewWalletInvite() {
175203 signersDescriptions : updatedDescriptions ,
176204 } ) ;
177205 }
206+ function getStakeAddress ( addr : string | undefined ) : string {
207+ if ( ! addr ) return "" ;
208+ try {
209+ // Deserialize the address to get the stake credential hash
210+ const stakeHash = deserializeAddress ( addr ) . stakeCredentialHash ;
211+ // Determine network based on address type
212+ const network = addr . includes ( "test" ) ? 0 : 1 ;
213+ // Serialize the stake address
214+ const stakeAddress = serializeRewardAddress ( stakeHash , false , network ) ;
215+ return stakeAddress || "" ;
216+ } catch ( e ) {
217+ return "" ;
218+ }
219+ }
178220
179221 return (
180222 < GlassMorphismPageWrapper >
181- < div className = "min-h-screen w-full overflow-x-hidden px-4 sm:px-6 lg:px-8 py-4 sm:py-6" >
182- < div className = "w-full max-w-4xl mx-auto" >
183-
223+ < div className = "min-h-screen w-full overflow-x-hidden px-4 py-4 sm:px-6 sm:py-6 lg:px-8" >
224+ < div className = "mx-auto w-full max-w-4xl" >
184225 { /* Main Title */ }
185226 < div className = "mb-4 sm:mb-6" >
186- < h1 className = "text-xl sm:text-2xl font-bold text-foreground" >
187- { newWallet ? ( isOwner || isAlreadySigner ? "New Wallet" : "Join New Wallet" ) : "" }
227+ < h1 className = "text-xl font-bold text-foreground sm:text-2xl" >
228+ { newWallet
229+ ? isOwner || isAlreadySigner
230+ ? "New Wallet"
231+ : "Join New Wallet"
232+ : "" }
188233 </ h1 >
189234 </ div >
190-
235+
191236 { /* Content Wrapper */ }
192237 < div className = "space-y-4 sm:space-y-6" >
193- { ! newWallet && (
194- < >
195- < Card >
196- < CardHeader >
197- < CardTitle > Page Not Found</ CardTitle >
198- </ CardHeader >
199- < CardContent >
200- < p className = "text-muted-foreground mb-4" >
201- This page is no longer available.
202- </ p >
203- </ CardContent >
204- </ Card >
205- < div className = "mt-6 flex sm:mt-8 sm:justify-end" >
206- < Button
207- onClick = { ( ) => router . push ( '/wallets' ) }
208- className = "w-full sm:w-auto"
209- size = "lg"
210- >
211- Go to Wallets
212- </ Button >
238+ { ! newWallet && ! showNotFound && (
239+ < div className = "flex h-32 items-center justify-center" >
240+ < div className = "loader" > Loading...</ div >
213241 </ div >
214- </ >
215- ) }
216- { newWallet && (
217- < div className = "space-y-4 sm:space-y-6" >
218- < WalletInfoCard
219- walletName = { newWallet . name }
220- walletDescription = { newWallet . description || undefined }
221- currentSignersCount = { newWallet . signersAddresses . length }
222- requiredSignatures = { newWallet . numRequiredSigners || 2 }
223- />
224-
225- { /* Owner or Already Signer - Show ManageSignerCard */ }
226- { ( isOwner || isAlreadySigner ) && (
227- < ManageSignerCard
228- userAddress = { userAddress || "" }
229- stakeAddress = { user ?. stakeAddress ?? "" }
230- signerName = { localSignerName }
231- onNameChange = { handleNameChange }
232- loading = { isUpdatingName }
233- walletId = { newWalletId }
234- isCreator = { isOwner }
235- />
236- ) }
237-
238- { /* Only Signers (not owner) get Remove button */ }
239- { isAlreadySigner && ! isOwner && (
240- < div className = "mt-6 sm:mt-8 flex justify-end" >
242+ ) }
243+ { ! newWallet && showNotFound && (
244+ < >
245+ < Card >
246+ < CardHeader >
247+ < CardTitle > Page Not Found</ CardTitle >
248+ </ CardHeader >
249+ < CardContent >
250+ < p className = "mb-4 text-muted-foreground" >
251+ This page is no longer available.
252+ </ p >
253+ </ CardContent >
254+ </ Card >
255+ < div className = "mt-6 flex sm:mt-8 sm:justify-end" >
241256 < Button
242- onClick = { handleRemoveClick }
243- disabled = { loading }
244- variant = "destructive"
257+ onClick = { ( ) => router . push ( "/wallets" ) }
245258 className = "w-full sm:w-auto"
246259 size = "lg"
247260 >
248- { loading ? "Removing..." : "Remove me from wallet" }
261+ Go to Wallets
249262 </ Button >
250263 </ div >
251- ) }
252-
253- { /* Not a signer yet - Show Join card */ }
254- { ! isOwner && ! isAlreadySigner && (
255- < >
256- < JoinAsSignerCard
264+ </ >
265+ ) }
266+ { newWallet && (
267+ < div className = "space-y-4 sm:space-y-6" >
268+ < WalletInfoCard
269+ walletName = { newWallet . name }
270+ walletDescription = { newWallet . description || undefined }
271+ currentSignersCount = { newWallet . signersAddresses . length }
272+ requiredSignatures = { newWallet . numRequiredSigners || 2 }
273+ />
274+
275+ { /* Owner or Already Signer - Show ManageSignerCard */ }
276+ { ( isOwner || isAlreadySigner ) && (
277+ < ManageSignerCard
257278 userAddress = { userAddress || "" }
258279 stakeAddress = { user ?. stakeAddress ?? "" }
259- signerName = { signersDescription }
260- setSignerName = { setSignerDescription }
261- onJoin = { addSigner }
262- loading = { loading }
280+ signerName = { localSignerName }
281+ onNameChange = { handleNameChange }
282+ loading = { isUpdatingName }
283+ walletId = { newWalletId }
284+ isCreator = { isOwner }
263285 />
264-
265- < div className = "mt-6 sm:mt-8 flex justify-end" >
286+ ) }
287+
288+ { /* Only Signers (not owner) get Remove button */ }
289+ { isAlreadySigner && ! isOwner && (
290+ < div className = "mt-6 flex justify-end sm:mt-8" >
266291 < Button
267- onClick = { addSigner }
292+ onClick = { handleRemoveClick }
268293 disabled = { loading }
294+ variant = "destructive"
269295 className = "w-full sm:w-auto"
270296 size = "lg"
271297 >
272- { loading ? "Adding ..." : "Add me as signer " }
298+ { loading ? "Removing ..." : "Remove me from wallet " }
273299 </ Button >
274300 </ div >
275- </ >
276- ) }
277- </ div >
278- ) }
301+ ) }
302+
303+ { /* Not a signer yet - Show Join card */ }
304+ { ! isOwner && ! isAlreadySigner && (
305+ < >
306+ < JoinAsSignerCard
307+ userAddress = { userAddress || "" }
308+ stakeAddress = { getStakeAddress ( userAddress ) ?? "" }
309+ signerName = { signersDescription }
310+ setSignerName = { setSignerDescription }
311+ onJoin = { addSigner }
312+ loading = { loading }
313+ />
314+
315+ < div className = "mt-6 flex justify-end sm:mt-8" >
316+ < Button
317+ onClick = { addSigner }
318+ disabled = { loading }
319+ className = "w-full sm:w-auto"
320+ size = "lg"
321+ >
322+ { loading ? "Adding..." : "Add me as signer" }
323+ </ Button >
324+ </ div >
325+ </ >
326+ ) }
327+ </ div >
328+ ) }
279329 </ div >
280330 </ div >
281331 </ div >
282-
332+
283333 { /* Remove Confirmation Dialog - same style as Create page */ }
284334 < Dialog open = { deleteDialogOpen } onOpenChange = { setDeleteDialogOpen } >
285- < DialogContent className = "sm:max-w-md bg-gray-50 dark:bg -neutral-800 border-gray-200 dark:border -neutral-700 shadow-xl " >
335+ < DialogContent className = "border-gray-200 bg-gray-50 shadow-xl dark:border -neutral-700 dark:bg -neutral-800 sm:max-w-md " >
286336 < DialogHeader >
287337 < DialogTitle > Remove from Wallet</ DialogTitle >
288338 < DialogDescription >
@@ -296,10 +346,7 @@ export default function PageNewWalletInvite() {
296346 >
297347 Cancel
298348 </ Button >
299- < Button
300- variant = "destructive"
301- onClick = { confirmRemove }
302- >
349+ < Button variant = "destructive" onClick = { confirmRemove } >
303350 Remove
304351 </ Button >
305352 </ DialogFooter >
0 commit comments