-
Notifications
You must be signed in to change notification settings - Fork 603
[MNY-239] Dashboard: Show webhook sends for Bridge webhooks #8213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
WalkthroughAdds authToken propagation across payments and webhooks UIs; expands the universal-bridge developer API to require auth tokens and adds webhook update, sends listing, and resend endpoints. Replaces webhooks table with a card-based CRUD UI and adds a Webhook Sends page/UI with pagination, detail view, and resend. Adds Storybook stories. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as User
participant Page as Webhooks Page
participant API as Developer API
participant UI as WebhookSends UI
U->>Page: Navigate to /webhooks/payments/[id]
Page->>API: fetch auth token & project
Page->>API: getWebhookById({clientId, teamId, authToken, webhookId})
API-->>Page: Webhook
Page-->>UI: Render WebhookSends({webhookId, authToken, projectClientId, teamId})
UI->>API: getWebhookSends({authToken, projectClientId, teamId, webhookId, limit, offset})
API-->>UI: {data, pagination}
U->>UI: Select item → UI shows details
U->>UI: Click Resend
UI->>API: resendWebhook({authToken, projectClientId, teamId, paymentId|onrampId})
API-->>UI: 200 / error
UI-->>U: show toast
sequenceDiagram
autonumber
actor U as User
participant List as Webhooks List UI
participant API as Developer API
U->>List: Click "Create Webhook"
List->>List: Open modal (create)
U->>List: Submit form
List->>API: createWebhook({clientId, teamId, authToken, ...})
API-->>List: Webhook
List->>List: Close modal, refresh list
U->>List: Edit webhook
List->>List: Open modal (edit)
U->>List: Submit updates
List->>API: updateWebhook({clientId, teamId, webhookId, authToken, body})
API-->>List: Webhook
List->>List: Close modal, refresh list
U->>List: Delete webhook
List->>API: deleteWebhook({clientId, teamId, webhookId, authToken})
API-->>List: true
List->>List: Refresh list
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Pre-merge checks and finishing touches❌ Failed checks (3 warnings)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8213 +/- ##
=======================================
Coverage 55.02% 55.02%
=======================================
Files 919 919
Lines 60583 60583
Branches 4127 4127
=======================================
Hits 33335 33335
Misses 27145 27145
Partials 103 103
🚀 New features to boost your workflow:
|
size-limit report 📦
|
7e188c6
to
5e2b22a
Compare
5e2b22a
to
38947bc
Compare
38947bc
to
6bed18b
Compare
c7ea93d
to
8542ebe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx (1)
338-338
: Fix incorrect button label.The button text reads "Delete Webhook" but this component manages payment links, not webhooks. This appears to be a copy-paste artifact from webhook-related code.
Apply this diff:
- Delete Webhook + Delete Paymentapps/dashboard/src/@/api/universal-bridge/developer.ts (1)
15-37
: Add explicit return types to async functions.Multiple async functions are missing explicit return type annotations, which conflicts with the coding guideline: "Use explicit function declarations and explicit return types in TypeScript."
Apply this diff to add explicit return types:
-export async function getWebhooks(params: { +export async function getWebhooks(params: { clientId: string; teamId: string; authToken: string; -}) { +}): Promise<Array<Webhook>> { -export async function getWebhookById(params: { +export async function getWebhookById(params: { clientId: string; teamId: string; authToken: string; webhookId: string; -}) { +}): Promise<Webhook> { -export async function createWebhook(params: { +export async function createWebhook(params: { clientId: string; teamId: string; version?: number; url: string; label: string; secret?: string; authToken: string; -}) { +}): Promise<Webhook> { -export async function deleteWebhook(params: { +export async function deleteWebhook(params: { clientId: string; teamId: string; webhookId: string; authToken: string; -}) { +}): Promise<boolean> { -export async function updateWebhook(params: { +export async function updateWebhook(params: { clientId: string; teamId: string; webhookId: string; authToken: string; body: { version?: number; url: string; label: string; }; -}) { +}): Promise<Webhook> { -export async function createPaymentLink(params: { +export async function createPaymentLink(params: { clientId: string; teamId: string; title: string; imageUrl?: string; intent: { destinationChainId: number; destinationTokenAddress: Address; receiver: Address; amount: bigint; purchaseData?: unknown; }; authToken: string; -}) { +}): Promise<PaymentLink> { -export async function deletePaymentLink(params: { +export async function deletePaymentLink(params: { clientId: string; teamId: string; paymentLinkId: string; authToken: string; -}) { +}): Promise<boolean> { -export async function updateFee(params: { +export async function updateFee(params: { clientId: string; teamId: string; feeRecipient: string; feeBps: number; authToken: string; -}) { +}): Promise<boolean> {As per coding guidelines.
Also applies to: 39-65, 67-98, 100-125, 127-160, 333-378, 380-405, 438-465
♻️ Duplicate comments (4)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx (2)
385-387
: Invalidate with the full query key.This issue was previously flagged. The query is registered with
["webhooks", props.clientId, props.teamId]
at line 85, but this invalidation only uses["webhooks", props.clientId]
. The missingteamId
prevents the cache from being invalidated correctly, leaving the UI stale after mutations.Apply this diff:
onSuccess: () => { return queryClient.invalidateQueries({ - queryKey: ["webhooks", props.clientId], + queryKey: ["webhooks", props.clientId, props.teamId], }); },Note: This same issue exists at lines 525-527 and 566-568 and must be fixed in all locations.
398-400
: Fix error message to reflect both create and edit operations.This issue was previously flagged. The error toast always displays "Failed to create webhook" even when editing.
Apply this diff:
onError: (err) => { - toast.error("Failed to create webhook", { + toast.error(`Failed to ${props.type === "create" ? "create" : "update"} webhook`, { description: err instanceof Error ? err.message : undefined, }); },apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx (2)
459-474
: Fix null check foronrampId
.The check
if (webhookSend.onrampId)
returnstrue
for any truthy value, but sinceonrampId
isstring | null
, this correctly returns"onramp"
only when the ID exists. However, for clarity and to align with the bot's prior comment, consider being more explicit.- if (webhookSend.onrampId) { + if (webhookSend.onrampId !== null) { return "onramp"; } + if (webhookSend.transactionId) { + return "transaction"; + }
252-261
: Correct the error message to match the checked identifier.The error message states "No transaction or onramp ID found" but the code checks
paymentId
, nottransactionId
.Apply this diff to fix the error message:
} else { - throw new Error("No transaction or onramp ID found"); + throw new Error("No paymentId or onrampId found for resend"); }
🧹 Nitpick comments (8)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx (1)
81-81
: Include authToken in React Query keys for proper cache isolation.The queryKeys at lines 81 and 102-107 omit
authToken
, which may cause cache collisions if different authenticated users access the sameclientId
/teamId
combination. This could expose data across user sessions or fail to refresh when token changes.Apply this diff to include authToken in the payment-links query:
- queryKey: ["payment-links", props.clientId, props.teamId], + queryKey: ["payment-links", props.clientId, props.teamId, props.authToken],Apply this diff to include authToken in the payment-link-usages query:
queryKey: [ "payment-link-usages", paymentLinksQuery.dataUpdatedAt, props.clientId, props.teamId, + props.authToken, ],
As per coding guidelines: "Use descriptive, stable
queryKeys
for React Query cache hits" and ensure proper cache scoping per authenticated user.Also applies to: 102-107
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx (1)
13-20
: Consider addingclassName
prop for consistency.Per the coding guidelines for dashboard components: "Expose a
className
prop on the root element of every component". While this component functions correctly without it, addingclassName
support would improve reusability and allow parent components to adjust spacing or styling if needed.export function QuickStartSection(props: { teamSlug: string; projectSlug: string; clientId: string; teamId: string; projectWalletAddress?: string; authToken: string; + className?: string; }) { return ( - <section> + <section className={props.className}>apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx (1)
66-72
: Consider exposing a className prop for layout flexibility.The dashboard coding guidelines recommend exposing a
className
prop on the root element of components. While this component appears to be a page-level component, adding this prop would improve flexibility for future layout adjustments.As per coding guidelines.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx (1)
34-36
: Align mocksuccess
field withresponseStatus
.The
responseStatus
is randomized to include error codes (500, 404), butsuccess
is hardcoded totrue
. This creates unrealistic mock data where failed deliveries (status >= 400) are marked as successful.Apply this diff to derive
success
fromresponseStatus
:const responseStatus = Math.random() > 0.5 ? (Math.random() > 0.5 ? 200 : 500) : 404; + const success = responseStatus >= 200 && responseStatus < 300;
Then use the computed value:
- success: true, + success: success, responseStatus: responseStatus,Also applies to: 136-136
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx (2)
33-48
: Consider exposing aclassName
prop for flexibility.Per coding guidelines, dashboard components should expose a
className
prop on their root element for styling flexibility. BothWebhookSends
andWebhookSendsUI
could benefit from this pattern.As per coding guidelines.
Add
className
to the props type and apply it to the root div:type WebhookSendsProps = { webhookId: string; authToken: string; projectClientId: string; teamId: string; + className?: string; };
Then apply it to the root element:
return ( - <div className="pt-4"> + <div className={cn("pt-4", props.className)}>Also applies to: 90-91
66-83
: ConfigurestaleTime
for optimal caching.The React Query configuration is missing a
staleTime
setting. Adding this prevents unnecessary refetches and improves performance.As per coding guidelines.
const webhookSendsQuery = useQuery({ queryKey: ["webhook-sends", props.webhookId, page], retry: false, refetchOnWindowFocus: false, + staleTime: 60_000, // 60 seconds queryFn: () =>
apps/dashboard/src/@/api/universal-bridge/developer.ts (2)
177-184
: Export WebhookSendsResponse type.
WebhookSendsResponse
is returned bygetWebhookSends
(Line 194) but is not exported. Callers may need this type to properly type the response.Apply this diff:
-type WebhookSendsResponse = { +export type WebhookSendsResponse = { data: WebhookSend[]; pagination: { limit: number; offset: number; total: number; }; };
222-225
: Standardize error handling across API functions.
getWebhookSends
andresendWebhook
parse error responses as JSON and access.message
(Lines 223-224, 264-265), while other functions useawait res.text()
(e.g., Lines 31-32). The JSON approach is fragile—it will throw if the error response is not JSON or lacks amessage
field.For consistency and resilience, align with the pattern used elsewhere:
if (!response.ok) { - const errorJson = await response.json(); - throw new Error(errorJson.message); + const text = await response.text(); + throw new Error(text); }Apply this pattern to both
getWebhookSends
(Lines 222-225) andresendWebhook
(Lines 263-266).Also applies to: 263-266
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (14)
apps/dashboard/src/@/api/universal-bridge/developer.ts
(13 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PayAnalytics.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentHistory.client.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
(4 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
(8 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
(9 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/PayConfig.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/PayConfig.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentHistory.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PayAnalytics.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}
: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/types
or localtypes.ts
barrels
Prefer type aliases over interface except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial
,Pick
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
**/*.{ts,tsx}
: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from@/types
where applicable
Prefertype
aliases overinterface
except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/dashboard/src/@/api/universal-bridge/developer.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/dashboard/src/@/api/universal-bridge/developer.ts
apps/{dashboard,playground-web}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/**/*.{ts,tsx}
: Import UI primitives from@/components/ui/*
(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
UseNavLink
for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()
from@/lib/utils
for conditional class logic
Use design system tokens (e.g.,bg-card
,border-border
,text-muted-foreground
)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()
to retrieve JWT from cookies on server side
UseAuthorization: Bearer
header – never embed tokens in URLs
Return typed results (e.g.,Project[]
,User[]
) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query
)
Use descriptive, stablequeryKeys
for React Query cache hits
ConfigurestaleTime
/cacheTime
in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-js
in server components
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/dashboard/src/@/api/universal-bridge/developer.ts
apps/{dashboard,playground}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{ts,tsx}
: Import UI primitives from@/components/ui/_
(e.g., Button, Input, Tabs, Card)
UseNavLink
for internal navigation to get active state handling
Use Tailwind CSS for styling; no inline styles
Merge class names withcn()
from@/lib/utils
for conditional classes
Stick to design tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components must start withimport "server-only"
; usenext/headers
, server‑only env, heavy data fetching, andredirect()
where appropriate
Client Components must start with'use client'
; handle interactivity with hooks and browser APIs
Server-side data fetching: callgetAuthToken()
from cookies, sendAuthorization: Bearer <token>
header, and return typed results (avoidany
)
Client-side data fetching: wrap calls in React Query with descriptive, stablequeryKeys
and set sensiblestaleTime/cacheTime
(≥ 60s default); keep tokens secret via internal routes or server actions
Do not importposthog-js
in server components (client-side only)
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/dashboard/src/@/api/universal-bridge/developer.ts
apps/{dashboard,playground}/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Expose a
className
prop on the root element of every component
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
**/*.stories.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
For new UI components, add Storybook stories (
*.stories.tsx
) alongside the code
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/{dashboard,playground}/**/*.stories.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Add Storybook stories (
*.stories.tsx
) alongside new UI components
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
🧠 Learnings (7)
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to apps/{dashboard,playground}/**/*.stories.tsx : Add Storybook stories (`*.stories.tsx`) alongside new UI components
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.stories.tsx : For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/components/*.{stories,test}.{tsx,ts} : Provide a Storybook story (`MyComponent.stories.tsx`) or unit test alongside the component.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout changes.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout PR #7888.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
🧬 Code graph analysis (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx (1)
WebhookSendsUI
(50-191)apps/dashboard/src/@/api/universal-bridge/developer.ts (2)
getWebhookSends
(186-228)WebhookSend
(162-175)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx (3)
apps/dashboard/src/@/api/universal-bridge/developer.ts (3)
getWebhookSends
(186-228)resendWebhook
(230-269)WebhookSend
(162-175)apps/dashboard/src/@/components/blocks/pagination-buttons.tsx (1)
PaginationButtons
(18-221)apps/dashboard/src/@/components/ui/CopyTextButton.tsx (1)
CopyTextButton
(9-68)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx (1)
apps/dashboard/src/@/api/universal-bridge/developer.ts (1)
getPaymentLinks
(290-331)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx (4)
apps/dashboard/src/@/api/universal-bridge/developer.ts (4)
getWebhooks
(15-37)Webhook
(6-13)createWebhook
(67-98)updateWebhook
(127-160)apps/dashboard/src/@/components/ui/CopyTextButton.tsx (1)
CopyTextButton
(9-68)apps/dashboard/src/@/utils/usedapp-external.ts (1)
shortenString
(3-7)apps/dashboard/src/@/components/ui/checkbox.tsx (2)
CheckboxWithLabel
(36-51)Checkbox
(34-34)
apps/dashboard/src/@/api/universal-bridge/developer.ts (1)
apps/dashboard/src/@/constants/public-envs.ts (1)
NEXT_PUBLIC_THIRDWEB_BRIDGE_HOST
(21-22)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Size
- GitHub Check: Analyze (javascript)
🔇 Additional comments (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx (1)
43-48
: LGTM! AuthToken propagation is correctly implemented.The authToken flow through the component hierarchy and into API calls follows secure patterns:
- Props are explicitly typed as
string
- Token is passed via
Authorization: Bearer
header (confirmed in API code)- All mutations and queries properly receive the token
The implementation aligns with the broader PR objective of adding authentication across payment and webhook components.
Also applies to: 67-72, 73-82, 84-108, 137-142, 233-237, 282-288, 292-302
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx (1)
166-283
: Excellent story coverage.The stories comprehensively cover loading, success (with various result counts), empty, and error states. The intentionally long timeout in the
Loading
story effectively demonstrates the loading UI.apps/dashboard/src/@/api/universal-bridge/developer.ts (1)
67-98
: Align createWebhook response parsing with other methods.
createWebhook currently returns raw JSON as Webhook, whereas getWebhooks, getWebhookById, and updateWebhook usejson.data
. Confirm whether POST/v1/developer/webhooks
returns a{ data: Webhook }
envelope; if so, change toreturn (await res.json()).data as Webhook;
.
...)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
Show resolved
Hide resolved
...)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
Show resolved
Hide resolved
...)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
Show resolved
Hide resolved
...)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
Show resolved
Hide resolved
8542ebe
to
305d0d8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/PayConfig.tsx (1)
30-30
: Avoid exposing authToken in client components.This client component (
"use client"
) now receivesauthToken
as a prop and passes it directly to API calls. This exposes the token in browser JavaScript, violating the coding guideline: "Keep tokens secret via internal API routes or server actions".Recommendation: Refactor to use a server action or internal API route that reads the token from secure cookies server-side and performs the authenticated operation.
Based on learnings and coding guidelines.
Also applies to: 52-52
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx (1)
19-19
: Avoid exposing authToken in client components.This client component receives
authToken
and forwards it toCreatePaymentLinkButton
, exposing the token in browser JavaScript. This violates the security guideline: "Keep tokens secret via internal API routes or server actions".Please refactor to use server actions or internal API routes that handle authentication server-side.
Based on learnings and coding guidelines.
Also applies to: 50-50
🧹 Nitpick comments (4)
apps/dashboard/src/@/api/universal-bridge/developer.ts (1)
6-13
: Consider documenting the optionalversion
field.The
version
field has a TODO comment indicating it should become mandatory after migration. Consider adding a JSDoc comment to clarify the migration timeline or expected behavior when this field is undefined.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx (1)
459-474
: Verify the type extraction logic.The function attempts to extract the event type from the webhook body. Consider adding a runtime type guard or validation for the
type
field to ensure type safety, especially sincebody
is typed asunknown
.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx (1)
172-174
: Excessive timeout in Loading story.The timeout of
1000000ms
(1000 seconds) is unnecessarily long for a Storybook loading state. Consider reducing it to a more reasonable value like30000ms
(30 seconds) or using an infinite loading state without a timeout if you want to showcase the loading UI indefinitely.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx (1)
206-206
: Consider explicit date parsing for robustness.While
date-fns
can handle ISO date strings, explicitly convertingwebhook.createdAt
to aDate
improves type safety and guards against future library version changes that may be stricter about input types.Apply this diff:
<p className="text-xs text-muted-foreground"> Created{" "} - {formatDistanceToNow(webhook.createdAt, { addSuffix: true })} + {formatDistanceToNow(new Date(webhook.createdAt), { addSuffix: true })} </p>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (14)
apps/dashboard/src/@/api/universal-bridge/developer.ts
(13 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PayAnalytics.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentHistory.client.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
(4 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
(8 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
(9 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/PayConfig.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PayAnalytics.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentHistory.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}
: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/types
or localtypes.ts
barrels
Prefer type aliases over interface except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial
,Pick
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
**/*.{ts,tsx}
: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from@/types
where applicable
Prefertype
aliases overinterface
except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/PayConfig.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
apps/dashboard/src/@/api/universal-bridge/developer.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/PayConfig.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
apps/dashboard/src/@/api/universal-bridge/developer.ts
apps/{dashboard,playground-web}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/**/*.{ts,tsx}
: Import UI primitives from@/components/ui/*
(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
UseNavLink
for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()
from@/lib/utils
for conditional class logic
Use design system tokens (e.g.,bg-card
,border-border
,text-muted-foreground
)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()
to retrieve JWT from cookies on server side
UseAuthorization: Bearer
header – never embed tokens in URLs
Return typed results (e.g.,Project[]
,User[]
) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query
)
Use descriptive, stablequeryKeys
for React Query cache hits
ConfigurestaleTime
/cacheTime
in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-js
in server components
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/PayConfig.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
apps/dashboard/src/@/api/universal-bridge/developer.ts
apps/{dashboard,playground}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{ts,tsx}
: Import UI primitives from@/components/ui/_
(e.g., Button, Input, Tabs, Card)
UseNavLink
for internal navigation to get active state handling
Use Tailwind CSS for styling; no inline styles
Merge class names withcn()
from@/lib/utils
for conditional classes
Stick to design tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components must start withimport "server-only"
; usenext/headers
, server‑only env, heavy data fetching, andredirect()
where appropriate
Client Components must start with'use client'
; handle interactivity with hooks and browser APIs
Server-side data fetching: callgetAuthToken()
from cookies, sendAuthorization: Bearer <token>
header, and return typed results (avoidany
)
Client-side data fetching: wrap calls in React Query with descriptive, stablequeryKeys
and set sensiblestaleTime/cacheTime
(≥ 60s default); keep tokens secret via internal routes or server actions
Do not importposthog-js
in server components (client-side only)
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/PayConfig.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
apps/dashboard/src/@/api/universal-bridge/developer.ts
apps/{dashboard,playground}/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Expose a
className
prop on the root element of every component
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/PayConfig.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
**/*.stories.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
For new UI components, add Storybook stories (
*.stories.tsx
) alongside the code
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/{dashboard,playground}/**/*.stories.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Add Storybook stories (
*.stories.tsx
) alongside new UI components
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
🧠 Learnings (11)
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Prefer API routes or server actions to keep tokens secret; the browser only sees relative paths.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/api/**/*.{ts,tsx} : Pass the token in the `Authorization: Bearer` header – never embed it in the URL.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Keep tokens secret via internal API routes or server actions
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to apps/{dashboard,playground}/**/*.stories.tsx : Add Storybook stories (`*.stories.tsx`) alongside new UI components
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/components/*.{stories,test}.{tsx,ts} : Provide a Storybook story (`MyComponent.stories.tsx`) or unit test alongside the component.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.stories.tsx : For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout changes.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout PR #7888.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
📚 Learning: 2025-05-21T05:17:31.283Z
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
🧬 Code graph analysis (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx (1)
WebhookSendsUI
(50-191)apps/dashboard/src/@/api/universal-bridge/developer.ts (2)
getWebhookSends
(186-228)WebhookSend
(162-175)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx (4)
apps/dashboard/src/@/api/universal-bridge/developer.ts (4)
getWebhooks
(15-37)Webhook
(6-13)createWebhook
(67-98)updateWebhook
(127-160)apps/dashboard/src/@/components/ui/CopyTextButton.tsx (1)
CopyTextButton
(9-68)apps/dashboard/src/@/utils/usedapp-external.ts (1)
shortenString
(3-7)apps/dashboard/src/@/components/ui/checkbox.tsx (2)
CheckboxWithLabel
(36-51)Checkbox
(34-34)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx (4)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx (1)
Page
(6-29)apps/dashboard/src/@/api/universal-bridge/developer.ts (1)
getWebhookById
(39-65)apps/dashboard/src/@/components/ui/CopyTextButton.tsx (1)
CopyTextButton
(9-68)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx (1)
WebhookSends
(40-48)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx (3)
apps/dashboard/src/@/api/universal-bridge/developer.ts (3)
getWebhookSends
(186-228)resendWebhook
(230-269)WebhookSend
(162-175)apps/dashboard/src/@/components/blocks/pagination-buttons.tsx (1)
PaginationButtons
(18-221)apps/dashboard/src/@/components/ui/CopyTextButton.tsx (1)
CopyTextButton
(9-68)
apps/dashboard/src/@/api/universal-bridge/developer.ts (1)
apps/dashboard/src/@/constants/public-envs.ts (1)
NEXT_PUBLIC_THIRDWEB_BRIDGE_HOST
(21-22)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Unit Tests
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (10)
apps/dashboard/src/@/api/universal-bridge/developer.ts (2)
162-175
: Well-structured type definition.The
WebhookSend
type clearly models the webhook event data with appropriate nullable fields and discriminated union-friendly structure.
186-228
: Solid implementation of paginated webhook sends.The
getWebhookSends
function properly:
- Uses URL search params for filters
- Includes authentication headers
- Handles errors with descriptive messages
- Returns properly typed response
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx (1)
23-23
: Proper async handling of params.Correctly awaits the
params
Promise as required in Next.js server components.Based on learnings.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx (2)
25-144
: Comprehensive mock data generator.The
createMockWebhookSendItem
function provides realistic test data covering multiple scenarios (bridge vs onramp, various statuses, JSON vs text responses), which is excellent for testing the UI across different states.
166-283
: Excellent story coverage.The stories cover all important UI states: loading, various data counts, empty state, error state, and resend error. This comprehensive coverage will help catch visual regressions and validate UX across different scenarios.
Based on coding guidelines requiring Storybook stories for new UI components.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx (1)
24-26
: LGTM! Props correctly threaded for webhook operations.The addition of
teamSlug
,projectSlug
, andauthToken
props enables authenticated webhook API calls and proper routing in the client component, consistent with the broader PR pattern.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx (4)
66-72
: LGTM! Props properly typed for webhook operations.The interface updates add the necessary identifiers (
teamSlug
,projectSlug
) and authentication (authToken
) required for webhook API calls and navigation throughout the component tree.
74-145
: LGTM! Card-based layout improves UX.The refactor from table to card-based layout with per-webhook actions (via dropdown) provides a modern, intuitive interface. The query correctly passes
authToken
, and the empty state clearly guides users to create their first webhook.
344-505
: LGTM! Unified modal content with type-safe discrimination.The discriminated union pattern cleanly handles create vs edit flows while sharing common form logic. The secret confirmation workflow (create-only) ensures users securely store credentials before proceeding.
507-581
: LGTM! Delete confirmation with proper mutation handling.The delete flow provides clear confirmation dialog and proper error/success handling with toast notifications.
type WebhookSendsProps = { | ||
webhookId: string; | ||
authToken: string; | ||
projectClientId: string; | ||
teamId: string; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid exposing authToken in client components.
This client component receives authToken
as a prop and uses it directly in React Query calls (line 73), exposing the token in browser JavaScript. According to coding guidelines: "Keep tokens secret via internal API routes or server actions".
Recommendation: Create a server action or internal API route (/api/...
) that reads the token from secure cookies and proxies the getWebhookSends
request server-side. The client component should call this API route without handling the token directly.
Based on learnings and coding guidelines.
Also applies to: 73-73
<!-- ## 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 payment and webhook functionalities in the dashboard application by adding `authToken` support across various components and improving the webhook management interface. ### Detailed summary - Added `authToken` prop to multiple components including `PayAnalytics`, `PaymentHistory`, and `QuickStartSection`. - Enhanced `getWebhooks`, `createWebhook`, `deleteWebhook`, and `updateWebhook` functions to accept `authToken`. - Improved the webhook management UI with `WebhookCard` and related functionalities. - Added dialog components for creating and editing webhooks with validation. - Updated API calls to include `authToken` for authentication in requests. > ✨ 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** - Card-based webhooks UI with create/edit modal, per-card actions, delete confirmation, webhook detail page, and webhook sends viewer (history, filtering, pagination, resend). - Payments area: payment links and payments viewer wired to authenticated CRUD and paginated payments list; resend and webhook-send actions supported. - **Enhancements** - authToken propagated across webhooks, payments, payment links, fees, and related components to enable authenticated operations. - Webhook objects no longer expose secret fields; create/update/delete now return usable payloads. - **Documentation** - Storybook stories added for webhook sends UI (loading, results, error, resend scenarios). <!-- end of auto-generated comment: release notes by coderabbit.ai -->
305d0d8
to
e74aca9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx (1)
47-54
: Remove authToken from client props; route create via server.This client component receives and uses authToken for network calls, exposing secrets in browser JS. Replace direct calls to createPaymentLink with:
- a Next.js server action, or
- an internal API route that reads the token from secure cookies and proxies the request.
Component should call the server action/route without handling secrets. As per coding guidelines.
Also applies to: 61-67, 73-79, 121-133
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx (3)
43-48
: Do not expose authToken in client; proxy via server actions/internal routes.authToken is accepted/passed through and used in client-side fetches/mutations, exposing it in browser JS. Move these calls behind server actions or internal API routes that read the token from cookies. Pass only non-secret params from the client. As per coding guidelines.
Also applies to: 57-63, 67-72, 73-81, 84-95, 137-143, 233-241, 282-289, 292-300
336-341
: Fix button label: this deletes a payment link, not a webhook.Change the button text to avoid user confusion.
Apply this diff:
- Delete Webhook + Delete Payment
205-221
: Avoid precision loss in revenue sum; accumulate as BigInt then format once.Using Number(toTokens(...)) can lose precision for large values. Sum raw wei as BigInt and call toTokens once.
Apply this diff:
- ) : ( - `${( - paymentLinkUsagesQuery.data - ?.find((x) => x.paymentLink.id === paymentLink.id) - ?.usages?.reduce( - (acc, curr) => - acc + - Number( - toTokens( - BigInt(curr.destinationAmount), - curr.destinationToken.decimals, - ), - ), - 0, - ) || 0 - ).toString()} ${paymentLink.destinationToken.symbol}` - )} + ) : ( + (() => { + const totalWei = + paymentLinkUsagesQuery.data + ?.find((x) => x.paymentLink.id === paymentLink.id) + ?.usages?.reduce( + (acc, curr) => acc + BigInt(curr.destinationAmount), + 0n, + ) ?? 0n; + const total = toTokens( + totalWei, + paymentLink.destinationToken.decimals, + ); + return `${total} ${paymentLink.destinationToken.symbol}`; + })() + )}
♻️ Duplicate comments (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx (1)
19-20
: authToken exposure in client component props (duplicate of earlier review).Passing authToken into this client component and forwarding it exposes the token to the browser. Please follow the prior guidance to use server actions/internal API routes instead.
Also applies to: 46-51
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx (4)
177-184
: Add aria-label to the dropdown trigger (duplicate of prior review).The icon-only trigger needs an accessible name.
Apply this diff:
<Button size="icon" variant="ghost" className="absolute right-4 top-4" + aria-label="Webhook actions" >
384-388
: Invalidate with the full query key (duplicate of prior review).Include teamId (and any other parts) so mutations refetch the list registered under ["webhooks", clientId, teamId].
Also applies to: 525-527, 566-569
397-401
: Use operation-appropriate error message (duplicate of prior review).Show "Failed to create webhook" vs "Failed to update webhook" based on props.type.
254-264
: Add explicit return types to async handlers (duplicate of prior review).Annotate as Promise to satisfy TS guidelines.
Also applies to: 299-311
🧹 Nitpick comments (6)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx (1)
1-1
: Mark server component explicitly.Add the server-only marker at the top to prevent accidental client bundling.
Apply this diff:
+import "server-only"; import Link from "next/link";
As per coding guidelines.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx (1)
94-100
: Set a sensible staleTime for queries.Add staleTime ≥ 60s per guidelines to avoid refetch churn.
Apply this diff:
const chainsQuery = useQuery({ queryFn: async () => { return await Bridge.chains({ client }); }, - queryKey: ["payments-chains"], + queryKey: ["payments-chains"], + staleTime: 60_000, });As per coding guidelines.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx (1)
72-83
: Add staleTime to queries to reduce refetch churn.Set staleTime ≥ 60s on both queries.
Apply these diffs:
const paymentLinksQuery = useQuery({ queryFn: async () => { return getPaymentLinks({ clientId: props.clientId, teamId: props.teamId, authToken: props.authToken, }); }, - queryKey: ["payment-links", props.clientId, props.teamId], + queryKey: ["payment-links", props.clientId, props.teamId], + staleTime: 60_000, });const paymentLinkUsagesQuery = useQuery({ queryFn: async () => { const paymentLinks = paymentLinksQuery.data || []; return await Promise.all( paymentLinks.map(async (paymentLink) => { const { data } = await getPayments({ authToken: props.authToken, clientId: props.clientId, teamId: props.teamId, paymentLinkId: paymentLink.id, }); return { paymentLink, usages: data, }; }), ); }, queryKey: [ "payment-link-usages", paymentLinksQuery.dataUpdatedAt, props.clientId, props.teamId, ], + staleTime: 60_000, });
As per coding guidelines.
Also applies to: 84-108
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx (1)
75-86
: Add staleTime to the webhooks list query.Reduce unnecessary refetches and align with guidelines.
Apply this diff:
const webhooksQuery = useQuery({ queryFn: async () => { const res = await getWebhooks({ clientId: props.clientId, teamId: props.teamId, authToken: props.authToken, }); return res; }, - queryKey: ["webhooks", props.clientId, props.teamId], + queryKey: ["webhooks", props.clientId, props.teamId], + staleTime: 60_000, });As per coding guidelines.
apps/dashboard/src/@/api/universal-bridge/developer.ts (2)
177-184
: Export WebhookSendsResponse type.The
WebhookSendsResponse
type is returned bygetWebhookSends
and may be needed by consumers for type-safe usage. Export it for consistency with other public types.Apply this diff:
-type WebhookSendsResponse = { +export type WebhookSendsResponse = { data: WebhookSend[]; pagination: { limit: number; offset: number; total: number; }; };
30-33
: Consider structured error handling.All error paths throw
new Error(text)
without context. Consider creating a structured error class that includes status code, error code, and request details to help consumers distinguish and handle different error types.Example:
class ApiError extends Error { constructor( message: string, public statusCode: number, public errorCode?: string, ) { super(message); this.name = 'ApiError'; } }Also applies to: 58-61, 92-95, 119-122, 152-155, 222-225, 263-266
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (14)
apps/dashboard/src/@/api/universal-bridge/developer.ts
(13 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PayAnalytics.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentHistory.client.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
(4 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
(8 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
(9 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/PayConfig.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PayAnalytics.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/PayConfig.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentHistory.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/payments/page.tsx
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}
: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/types
or localtypes.ts
barrels
Prefer type aliases over interface except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial
,Pick
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
**/*.{ts,tsx}
: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from@/types
where applicable
Prefertype
aliases overinterface
except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
apps/dashboard/src/@/api/universal-bridge/developer.ts
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
apps/dashboard/src/@/api/universal-bridge/developer.ts
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/**/*.{ts,tsx}
: Import UI primitives from@/components/ui/*
(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
UseNavLink
for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()
from@/lib/utils
for conditional class logic
Use design system tokens (e.g.,bg-card
,border-border
,text-muted-foreground
)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()
to retrieve JWT from cookies on server side
UseAuthorization: Bearer
header – never embed tokens in URLs
Return typed results (e.g.,Project[]
,User[]
) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query
)
Use descriptive, stablequeryKeys
for React Query cache hits
ConfigurestaleTime
/cacheTime
in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-js
in server components
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
apps/dashboard/src/@/api/universal-bridge/developer.ts
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/{dashboard,playground}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{ts,tsx}
: Import UI primitives from@/components/ui/_
(e.g., Button, Input, Tabs, Card)
UseNavLink
for internal navigation to get active state handling
Use Tailwind CSS for styling; no inline styles
Merge class names withcn()
from@/lib/utils
for conditional classes
Stick to design tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components must start withimport "server-only"
; usenext/headers
, server‑only env, heavy data fetching, andredirect()
where appropriate
Client Components must start with'use client'
; handle interactivity with hooks and browser APIs
Server-side data fetching: callgetAuthToken()
from cookies, sendAuthorization: Bearer <token>
header, and return typed results (avoidany
)
Client-side data fetching: wrap calls in React Query with descriptive, stablequeryKeys
and set sensiblestaleTime/cacheTime
(≥ 60s default); keep tokens secret via internal routes or server actions
Do not importposthog-js
in server components (client-side only)
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
apps/dashboard/src/@/api/universal-bridge/developer.ts
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
apps/{dashboard,playground}/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Expose a
className
prop on the root element of every component
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/CreatePaymentLinkButton.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
**/*.stories.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
For new UI components, add Storybook stories (
*.stories.tsx
) alongside the code
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/{dashboard,playground}/**/*.stories.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Add Storybook stories (
*.stories.tsx
) alongside new UI components
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
🧠 Learnings (11)
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout changes.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout PR #7888.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
📚 Learning: 2025-05-21T05:17:31.283Z
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to apps/{dashboard,playground}/**/*.stories.tsx : Add Storybook stories (`*.stories.tsx`) alongside new UI components
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/components/*.{stories,test}.{tsx,ts} : Provide a Storybook story (`MyComponent.stories.tsx`) or unit test alongside the component.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.stories.tsx : For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Prefer API routes or server actions to keep tokens secret; the browser only sees relative paths.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/api/**/*.{ts,tsx} : Pass the token in the `Authorization: Bearer` header – never embed it in the URL.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Keep tokens secret via internal API routes or server actions
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/QuickstartSection.client.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
🧬 Code graph analysis (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx (1)
Page
(6-29)apps/dashboard/src/@/api/universal-bridge/developer.ts (1)
getWebhookById
(39-65)apps/dashboard/src/@/components/ui/CopyTextButton.tsx (1)
CopyTextButton
(9-68)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/webhook-sends.tsx (1)
WebhookSendsUI
(50-191)apps/dashboard/src/@/api/universal-bridge/developer.ts (2)
getWebhookSends
(186-228)WebhookSend
(162-175)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx (1)
apps/dashboard/src/@/api/universal-bridge/developer.ts (1)
getPaymentLinks
(290-331)
apps/dashboard/src/@/api/universal-bridge/developer.ts (1)
apps/dashboard/src/@/constants/public-envs.ts (1)
NEXT_PUBLIC_THIRDWEB_BRIDGE_HOST
(21-22)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx (4)
apps/dashboard/src/@/api/universal-bridge/developer.ts (4)
getWebhooks
(15-37)Webhook
(6-13)createWebhook
(67-98)updateWebhook
(127-160)apps/dashboard/src/@/components/ui/CopyTextButton.tsx (1)
CopyTextButton
(9-68)apps/dashboard/src/@/utils/usedapp-external.ts (1)
shortenString
(3-7)apps/dashboard/src/@/components/ui/checkbox.tsx (2)
CheckboxWithLabel
(36-51)Checkbox
(34-34)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Size
- GitHub Check: Analyze (javascript)
🔇 Additional comments (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/WebhookSendsUI.stories.tsx (1)
8-18
: Stories look solid.Good coverage of loading/success/error scenarios with typed mocks.
Also applies to: 166-183
apps/dashboard/src/@/api/universal-bridge/developer.ts (4)
15-37
: LGTM: Authentication implementation.All API functions correctly implement Bearer token authentication with proper header usage (
Authorization: Bearer
,x-client-id
,x-team-id
). Tokens are never embedded in URLs, following security best practices.Also applies to: 39-65, 67-98, 100-125, 127-160, 186-228, 230-269
46-46
: LGTM: Path parameter encoding.All dynamic path parameters are properly encoded using
encodeURIComponent
, preventing path traversal and handling special characters correctly.Also applies to: 107-107, 139-139, 387-387
230-254
: LGTM: Discriminated union type for resendWebhook.The discriminated union enforces that callers provide either
paymentId
oronrampId
(but not both) at compile time, which is excellent type safety. The implementation correctly serializes the appropriate field based on the discriminant.
186-228
: LGTM: getWebhookSends implementation.The function correctly uses the URL API for safe query parameter construction, properly handles optional parameters, and includes an explicit return type.
export async function getWebhooks(params: { | ||
clientId: string; | ||
teamId: string; | ||
authToken: string; | ||
}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add explicit return types to async functions.
Per coding guidelines, all functions must have explicit return types. The following functions are missing return type annotations:
getWebhooks
→Promise<Webhook[]>
getWebhookById
→Promise<Webhook>
createWebhook
→Promise<Webhook>
deleteWebhook
→Promise<boolean>
updateWebhook
→Promise<Webhook>
resendWebhook
→Promise<boolean>
createPaymentLink
→Promise<PaymentLink>
deletePaymentLink
→Promise<boolean>
getFees
→Promise<Fee>
updateFee
→Promise<boolean>
getPayments
→Promise<PaymentsResponse>
As per coding guidelines.
Example for getWebhooks
:
-export async function getWebhooks(params: {
+export async function getWebhooks(params: {
clientId: string;
teamId: string;
authToken: string;
-}) {
+}): Promise<Webhook[]> {
Also applies to: 39-44, 67-75, 100-105, 127-137, 230-243, 333-346, 380-385, 414-418, 438-444, 521-528
🤖 Prompt for AI Agents
In apps/dashboard/src/@/api/universal-bridge/developer.ts around lines 15-19
(and also update the functions at the listed ranges 39-44, 67-75, 100-105,
127-137, 230-243, 333-346, 380-385, 414-418, 438-444, 521-528), add explicit
TypeScript return type annotations to each async function per the coding
guidelines (e.g. getWebhooks: Promise<Webhook[]>, getWebhookById:
Promise<Webhook>, createWebhook: Promise<Webhook>, deleteWebhook:
Promise<boolean>, updateWebhook: Promise<Webhook>, resendWebhook:
Promise<boolean>, createPaymentLink: Promise<PaymentLink>, deletePaymentLink:
Promise<boolean>, getFees: Promise<Fee>, updateFee: Promise<boolean>,
getPayments: Promise<PaymentsResponse>), ensuring the declared return types
match the actual resolved values returned by each function and updating any
imports/types if needed.
type PayWebhooksPageProps = { | ||
clientId: string; | ||
teamId: string; | ||
teamSlug: string; | ||
authToken: string; | ||
projectSlug: string; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not expose authToken in client; move fetches/mutations server-side.
This file accepts and uses authToken in client-side queries/mutations, exposing secrets. Use server actions or internal API routes that read the token from cookies; keep client free of secrets. As per coding guidelines.
Also applies to: 75-85, 186-199, 507-512, 517-523
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
around lines 66-72 (and also affecting lines 75-85, 186-199, 507-512, 517-523):
the component currently accepts and uses authToken in client-side props which
exposes secrets; remove authToken from the client props and stop doing
fetches/mutations with it in the browser. Instead implement server-side handlers
(either Next.js server actions or internal API routes) that read the auth token
from secure cookies/session on the server, move all fetch/mutation logic into
those server endpoints/actions, update the client component to call those
endpoints/actions (passing only non-secret data like IDs or slugs), and update
the component prop types and all call sites to stop passing authToken. Ensure
error handling and types are preserved, and audit the listed line ranges to
remove any remaining direct uses of authToken in client code.
Created{" "} | ||
{formatDistanceToNow(webhook.createdAt, { addSuffix: true })} | ||
</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix type error: pass a Date to formatDistanceToNow.
createdAt is a string; date-fns expects Date | number.
Apply this diff:
- {formatDistanceToNow(webhook.createdAt, { addSuffix: true })}
+ {formatDistanceToNow(new Date(webhook.createdAt), { addSuffix: true })}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
Created{" "} | |
{formatDistanceToNow(webhook.createdAt, { addSuffix: true })} | |
</p> | |
Created{" "} | |
{formatDistanceToNow(new Date(webhook.createdAt), { addSuffix: true })} | |
</p> |
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/webhooks/components/webhooks.client.tsx
around lines 205-207, formatDistanceToNow is being passed webhook.createdAt
which is a string; convert it to a Date (or timestamp) before calling
formatDistanceToNow. Update the call to pass new Date(webhook.createdAt) (or
Date.parse(webhook.createdAt)) and optionally guard against invalid dates (e.g.,
check isNaN(date.getTime()) and provide a fallback) so the function receives a
Date | number as required.
if (!webhook) { | ||
notFound(); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unreachable check for missing webhook.
getWebhookById throws on non-OK responses; this if (!webhook) notFound()
never runs. Either:
- catch and map 404 to notFound here, or
- change getWebhookById to return null on 404.
Otherwise remove the dead check to avoid confusion.
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
around lines 38-41, the if (!webhook) notFound() check is unreachable because
getWebhookById throws on non-OK responses; either wrap the call in a try/catch
and call notFound() when the caught error indicates a 404, or change
getWebhookById to return null for 404 responses so the existing null-check is
meaningful; remove the dead check if you choose to keep throwing behavior and
handle routing upstream.
<WebhookSends | ||
webhookId={params.id} | ||
authToken={authToken} | ||
projectClientId={project.publishableKey} | ||
teamId={project.teamId} | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not pass authToken to client components; proxy via server actions/internal API.
authToken is forwarded to WebhookSends (client), exposing it in browser JS. Move fetches/resend to a server action or an internal API route that reads the token from cookies. Pass only non-secret data/IDs to the client. As per coding guidelines.
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/[id]/page.tsx
around lines 75-80, you are passing authToken into the client component
WebhookSends which exposes secrets to browser JS; remove the authToken prop and
instead implement a server-side endpoint or Next.js server action that performs
fetches/resend using the auth token read from cookies/session on the server,
then have WebhookSends call that internal API (or invoke the server action) with
only non-secret identifiers (webhookId, projectClientId, teamId) so all
sensitive operations remain server-side.
PR-Codex overview
This PR introduces the
authToken
parameter across various components and API functions related to payments and webhooks, enhancing authentication handling. It also includes the implementation of new webhook functionalities, improving user interaction with webhook management.Detailed summary
authToken
prop to multiple components includingPayAnalytics
,PaymentHistory
, andQuickStartSection
.authToken
for webhooks and payment links.WebhookCard
.Summary by CodeRabbit
New Features
Enhancements
Documentation