Skip to content

Commit 5b753d2

Browse files
committed
Add webhook creation UI to dashboard (#7174)
<!-- ## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes" If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000): ## Notes for the reviewer Anything important to call out? Be sure to also clarify these in your comments. ## How to test Unit tests, playground, etc. --> <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on enhancing the `CreateWebhookModal` component and related functionalities for managing webhooks in the dashboard. It introduces new features for creating webhooks, including form validation, ABI fetching, and improved user experience. ### Detailed summary - Changed `createWebhook` function to be exported. - Updated `CreateWebhookModal` to accept `clientId` and handle multi-step creation. - Added form handling with validation using `zod`. - Implemented steps for basic info, filter details, and review. - Integrated ABI fetching for events and transactions. - Enhanced error handling and user feedback with toast notifications. - Updated `WebhooksTable` to include `clientId` in the modal. - Improved `RelativeTime` component by removing unused utility function. - Added utility functions for parsing addresses and building webhook payloads. - Enhanced form validation for webhook creation with specific constraints. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a multi-step modal form for creating webhooks, including form validation, ABI integration, and live endpoint testing. - Added components for basic info entry, filter configuration, and review before submission. - Enabled dynamic ABI fetching and signature extraction for blockchain event and transaction filters. - Improved error handling and user feedback throughout the webhook creation flow. - **Bug Fixes** - Enhanced validation and error messages for webhook URLs and date handling in tables. - **Chores** - Added comprehensive utility modules for ABI processing and webhook payload construction. - Implemented robust type definitions and validation schemas for webhook forms. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent b1e702d commit 5b753d2

File tree

13 files changed

+1818
-13
lines changed

13 files changed

+1818
-13
lines changed

apps/dashboard/src/@/api/insight/webhooks.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ interface TestWebhookResponse {
6767
error?: string;
6868
}
6969

70-
// biome-ignore lint/correctness/noUnusedVariables: will be used in the next PR
71-
async function createWebhook(
70+
export async function createWebhook(
7271
payload: CreateWebhookPayload,
7372
clientId: string,
7473
): Promise<WebhookSingleResponse> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
"use client";
2+
3+
import { Button } from "@/components/ui/button";
4+
import {
5+
FormControl,
6+
FormField,
7+
FormItem,
8+
FormLabel,
9+
FormMessage,
10+
} from "@/components/ui/form";
11+
import { Input } from "@/components/ui/input";
12+
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
13+
import { cn } from "@/lib/utils";
14+
import type { UseFormReturn } from "react-hook-form";
15+
import type { WebhookFormValues } from "../utils/webhookTypes";
16+
17+
interface BasicInfoStepProps {
18+
form: UseFormReturn<WebhookFormValues>;
19+
goToNextStep: () => void;
20+
isLoading: boolean;
21+
}
22+
23+
export default function BasicInfoStep({
24+
form,
25+
goToNextStep,
26+
isLoading,
27+
}: BasicInfoStepProps) {
28+
return (
29+
<>
30+
<div className="mb-4">
31+
<h2 className="font-medium text-lg">Step 1: Basic Information</h2>
32+
<p className="text-muted-foreground text-sm">
33+
Provide webhook details and select filter type
34+
</p>
35+
</div>
36+
37+
<FormField
38+
control={form.control}
39+
name="name"
40+
render={({ field }) => (
41+
<FormItem className="flex flex-col">
42+
<FormLabel>
43+
Name <span className="text-red-500">*</span>
44+
</FormLabel>
45+
<FormControl>
46+
<Input
47+
placeholder="Webhook name"
48+
value={field.value}
49+
onChange={field.onChange}
50+
/>
51+
</FormControl>
52+
<FormMessage />
53+
</FormItem>
54+
)}
55+
/>
56+
57+
<FormField
58+
control={form.control}
59+
name="webhookUrl"
60+
render={({ field }) => (
61+
<FormItem className="mt-4 flex flex-col">
62+
<FormLabel>
63+
Webhook URL <span className="text-red-500">*</span>
64+
</FormLabel>
65+
<FormControl>
66+
<Input
67+
placeholder="https://your-server.com/webhook"
68+
type="url"
69+
value={field.value}
70+
onChange={field.onChange}
71+
/>
72+
</FormControl>
73+
<FormMessage />
74+
</FormItem>
75+
)}
76+
/>
77+
78+
<FormField
79+
control={form.control}
80+
name="filterType"
81+
render={({ field }) => (
82+
<FormItem className="mt-6 flex flex-col">
83+
<FormLabel>
84+
Filter Type <span className="text-red-500">*</span>
85+
</FormLabel>
86+
<FormControl>
87+
<RadioGroup
88+
onValueChange={(value: string) => {
89+
if (value !== "event" && value !== "transaction") {
90+
return;
91+
}
92+
field.onChange(value);
93+
// Ensure the form state is updated immediately
94+
form.setValue("filterType", value, {
95+
shouldValidate: true,
96+
shouldDirty: true,
97+
});
98+
}}
99+
value={field.value || undefined}
100+
className="grid grid-cols-1 gap-4 md:grid-cols-2"
101+
>
102+
<div className="col-span-1">
103+
<label
104+
htmlFor="filter-event"
105+
className={cn(
106+
"flex cursor-pointer flex-col rounded-lg border-2 p-4 hover:border-primary/50",
107+
field.value === "event"
108+
? "border-primary bg-primary/5"
109+
: "",
110+
)}
111+
>
112+
<RadioGroupItem
113+
value="event"
114+
id="filter-event"
115+
className="sr-only"
116+
/>
117+
<div className="mb-2 flex items-center justify-between">
118+
<span className="font-medium text-base">Event</span>
119+
<div
120+
className={cn(
121+
"flex h-5 w-5 items-center justify-center rounded-full border",
122+
field.value === "event"
123+
? "border-primary"
124+
: "border-muted-foreground",
125+
)}
126+
>
127+
{field.value === "event" && (
128+
<div className="h-3 w-3 rounded-full bg-primary" />
129+
)}
130+
</div>
131+
</div>
132+
<span className="text-muted-foreground text-sm">
133+
Listen for contract events like token transfers or state
134+
changes
135+
</span>
136+
</label>
137+
</div>
138+
139+
<div className="col-span-1">
140+
<label
141+
htmlFor="filter-transaction"
142+
className={cn(
143+
"flex cursor-pointer flex-col rounded-lg border-2 p-4 hover:border-primary/50",
144+
field.value === "transaction"
145+
? "border-primary bg-primary/5"
146+
: "",
147+
)}
148+
>
149+
<RadioGroupItem
150+
value="transaction"
151+
id="filter-transaction"
152+
className="sr-only"
153+
/>
154+
<div className="mb-2 flex items-center justify-between">
155+
<span className="font-medium text-base">Transaction</span>
156+
<div
157+
className={cn(
158+
"flex h-5 w-5 items-center justify-center rounded-full border",
159+
field.value === "transaction"
160+
? "border-primary"
161+
: "border-muted-foreground",
162+
)}
163+
>
164+
{field.value === "transaction" && (
165+
<div className="h-3 w-3 rounded-full bg-primary" />
166+
)}
167+
</div>
168+
</div>
169+
<span className="text-muted-foreground text-sm">
170+
Listen for blockchain transactions with specific
171+
parameters
172+
</span>
173+
</label>
174+
</div>
175+
</RadioGroup>
176+
</FormControl>
177+
<FormMessage />
178+
</FormItem>
179+
)}
180+
/>
181+
182+
<div className="mt-6 flex justify-end">
183+
<Button type="button" onClick={goToNextStep} disabled={isLoading}>
184+
Next
185+
</Button>
186+
</div>
187+
</>
188+
);
189+
}

0 commit comments

Comments
 (0)