Skip to content

Commit 706156b

Browse files
committed
Adding validations
1 parent 786e664 commit 706156b

File tree

2 files changed

+105
-106
lines changed

2 files changed

+105
-106
lines changed
Lines changed: 93 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client";
22

33
import type { Project } from "@/api/projects";
4-
import { type Fee, updateFee } from "@/api/universal-bridge/developer";
4+
import type { Fee } from "@/api/universal-bridge/developer";
55
import { RouteDiscoveryCard } from "@/components/blocks/RouteDiscoveryCard";
66
import {
77
Form,
@@ -12,15 +12,14 @@ import {
1212
} from "@/components/ui/form";
1313
import { Input } from "@/components/ui/input";
1414
import { zodResolver } from "@hookform/resolvers/zod";
15-
import { useMutation } from "@tanstack/react-query";
1615
import { NetworkSelectorButton } from "components/selects/NetworkSelectorButton";
1716
import {
18-
type ApiKeyPayConfigValidationSchema,
19-
apiKeyPayConfigValidationSchema,
17+
type RouteDiscoveryValidationSchema,
18+
routeDiscoveryValidationSchema,
2019
} from "components/settings/ApiKeys/validations";
2120
import { useTrack } from "hooks/analytics/useTrack";
21+
import { useState } from "react";
2222
import { useForm } from "react-hook-form";
23-
import { toast } from "sonner";
2423

2524
interface PayConfigProps {
2625
project: Project;
@@ -32,120 +31,108 @@ interface PayConfigProps {
3231
const TRACKING_CATEGORY = "pay";
3332

3433
export const RouteDiscovery: React.FC<PayConfigProps> = (props) => {
35-
const form = useForm<ApiKeyPayConfigValidationSchema>({
36-
resolver: zodResolver(apiKeyPayConfigValidationSchema),
37-
values: {
38-
payoutAddress: props.fees.feeRecipient ?? "",
39-
developerFeeBPS: props.fees.feeBps ? props.fees.feeBps / 100 : 0,
34+
const [isSubmitSuccess, setIsSubmitSuccess] = useState(false);
35+
const form = useForm<RouteDiscoveryValidationSchema>({
36+
resolver: zodResolver(routeDiscoveryValidationSchema),
37+
defaultValues: {
38+
tokenAddress: "",
4039
},
4140
});
4241

4342
const trackEvent = useTrack();
4443

45-
const updateFeeMutation = useMutation({
46-
mutationFn: async (values: {
47-
payoutAddress: string;
48-
developerFeeBPS: number;
49-
}) => {
50-
await updateFee({
51-
clientId: props.project.publishableKey,
52-
teamId: props.teamId,
53-
feeRecipient: values.payoutAddress,
54-
feeBps: values.developerFeeBPS,
55-
});
56-
},
57-
});
58-
5944
const handleSubmit = form.handleSubmit(
60-
({ payoutAddress, developerFeeBPS }) => {
61-
updateFeeMutation.mutate(
62-
{
63-
payoutAddress,
64-
developerFeeBPS: developerFeeBPS ? developerFeeBPS * 100 : 0,
65-
},
66-
{
67-
onSuccess: () => {
68-
toast.success("Fee sharing updated");
69-
trackEvent({
70-
category: TRACKING_CATEGORY,
71-
action: "configuration-update",
72-
label: "success",
73-
data: {
74-
payoutAddress,
75-
},
76-
});
77-
},
78-
onError: (err) => {
79-
toast.error("Failed to update fee sharing");
80-
console.error(err);
81-
trackEvent({
82-
category: TRACKING_CATEGORY,
83-
action: "configuration-update",
84-
label: "error",
85-
error: err,
86-
});
87-
},
88-
},
89-
);
45+
() => {
46+
console.log("Button pressed");
47+
setIsSubmitSuccess(true);
9048
},
9149
(errors) => {
9250
console.log(errors);
9351
},
9452
);
9553

54+
// Success component shown after successful submission
55+
const SuccessComponent = () => (
56+
<div className="bg-green-50 border border-green-200 rounded-md p-4 mt-4">
57+
<h4 className="text-green-600 font-medium text-lg">
58+
Token submitted successfully!
59+
</h4>
60+
<p className="text-green-600">
61+
Thank you for your submission. If you still do not see your token listed
62+
after some time, please reach out to our team for support.
63+
</p>
64+
</div>
65+
);
66+
9667
return (
97-
<Form {...form}>
98-
<form onSubmit={handleSubmit} autoComplete="off">
99-
<RouteDiscoveryCard
100-
bottomText=""
101-
errorText={form.getFieldState("payoutAddress").error?.message}
102-
saveButton={{
103-
type: "submit",
104-
disabled: !form.formState.isDirty,
105-
isPending: updateFeeMutation.isPending,
106-
variant: "primary",
107-
}}
108-
noPermissionText={undefined}
109-
>
110-
<div>
111-
<h3 className="font-semibold text-xl tracking-tight">
112-
Don't see your token listed?
113-
</h3>
114-
<p className="mt-1.5 mb-4 text-foreground text-sm">
115-
Select your chain and input the token address to automatically
116-
kick-off the toke route discovery process. Please check back on
117-
this page within 20-40 minutes of submitting this form.
118-
</p>
68+
<RouteDiscoveryCard
69+
bottomText=""
70+
saveButton={
71+
!isSubmitSuccess
72+
? {
73+
type: "submit",
74+
form: "route-discovery-form", // Connect to form by ID
75+
disabled: !form.formState.isDirty || form.formState.isSubmitting,
76+
variant: "primary",
77+
}
78+
: undefined
79+
}
80+
noPermissionText={undefined}
81+
>
82+
<div>
83+
<h3 className="font-semibold text-xl tracking-tight">
84+
Don't see your token listed?
85+
</h3>
86+
<p className="mt-1.5 mb-4 text-foreground text-sm">
87+
Select your chain and input the token address to automatically
88+
kick-off the token route discovery process. Please check back on this
89+
page within 20-40 minutes of submitting this form.
90+
</p>
11991

120-
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
121-
<FormField
122-
control={form.control}
123-
name="blockchain"
124-
render={({ field }) => (
125-
<FormItem>
126-
<FormLabel>Blockchain</FormLabel>
127-
<NetworkSelectorButton />
128-
</FormItem>
129-
)}
130-
/>
131-
<FormField
132-
control={form.control}
133-
name="tokenAddress"
134-
render={({ field }) => (
135-
<FormItem>
136-
<FormLabel>Token Address</FormLabel>
137-
<FormControl>
138-
<div className="flex items-center gap-2">
139-
<Input {...field} placeholder="0x..." />
140-
</div>
141-
</FormControl>
142-
</FormItem>
143-
)}
144-
/>
145-
</div>
146-
</div>
147-
</RouteDiscoveryCard>
148-
</form>
149-
</Form>
92+
{isSubmitSuccess ? (
93+
// Show success message after successful submission
94+
<SuccessComponent />
95+
) : (
96+
// Show form when not yet successfully submitted
97+
<Form {...form}>
98+
<form onSubmit={handleSubmit} autoComplete="off">
99+
autoComplete="off"
100+
>
101+
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
102+
<FormField
103+
control={form.control}
104+
name="blockchain"
105+
render={({ field }) => (
106+
<FormItem>
107+
<FormLabel>Blockchain</FormLabel>
108+
<FormControl>
109+
<NetworkSelectorButton
110+
value={field.value}
111+
onChange={field.onChange}
112+
/>
113+
</FormControl>
114+
</FormItem>
115+
)}
116+
/>
117+
<FormField
118+
control={form.control}
119+
name="tokenAddress"
120+
render={({ field }) => (
121+
<FormItem>
122+
<FormLabel>Token Address</FormLabel>
123+
<FormControl>
124+
<div className="flex items-center gap-2">
125+
<Input {...field} placeholder="0x..." />
126+
</div>
127+
</FormControl>
128+
</FormItem>
129+
)}
130+
/>
131+
</div>
132+
</form>
133+
</Form>
134+
)}
135+
</div>
136+
</RouteDiscoveryCard>
150137
);
151138
};

apps/dashboard/src/components/settings/ApiKeys/validations.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,18 @@ export const apiKeyPayConfigValidationSchema = z.object({
123123
.optional(),
124124
});
125125

126+
export const routeDiscoveryValidationSchema = z.object({
127+
tokenAddress: z
128+
.string({
129+
required_error: "Token address is required",
130+
})
131+
.min(1, "Token address is required")
132+
.regex(/^0x[a-fA-F0-9]{40}$/, "Invalid contract address format"),
133+
});
134+
export type RouteDiscoveryValidationSchema = z.infer<
135+
typeof routeDiscoveryValidationSchema
136+
>;
137+
126138
export type ApiKeyEmbeddedWalletsValidationSchema = z.infer<
127139
typeof apiKeyEmbeddedWalletsValidationSchema
128140
>;

0 commit comments

Comments
 (0)