Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@steven-tey
Copy link
Collaborator

@steven-tey steven-tey commented Jun 6, 2025

Summary by CodeRabbit

  • Refactor

    • Simplified all program-related URLs and navigation by removing dynamic program ID segments from paths, switching from plural "programs" to singular "program".
    • Updated data fetching hooks and actions to internally determine the program ID from workspace context, eliminating the need to pass or extract program IDs from route parameters.
    • Streamlined component props and internal logic to remove dependencies on program ID from URL parameters.
    • Unified and simplified redirect and sidebar navigation logic for program routes.
    • Refined reward and payout count queries to include all relevant rewards and order results by count.
  • Bug Fixes

    • Improved consistency and reliability of program-related data fetching and navigation by centralizing program ID resolution.
  • Chores

    • Removed unused parameters and imports across multiple components and hooks for cleaner code and improved maintainability.

@vercel
Copy link
Contributor

vercel bot commented Jun 6, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
dub ✅ Ready (Inspect) Visit Preview Jun 7, 2025 1:33am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 6, 2025

## Walkthrough

This update removes the dependency on explicit `programId` parameters throughout the codebase, instead deriving the program ID from the workspace context using `getDefaultProgramIdOrThrow` or `useWorkspace`. All API endpoints, hooks, and UI routes are refactored to use simplified paths without dynamic program ID segments, consolidating program-related navigation and logic under a singular `/program` route.

## Changes

| File(s) / Area                                                                                                         | Change Summary                                                                                                                                                                                                                                                                                                                                                         |
|------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `apps/web/app/(ee)/api/partners/count/route.ts`, `/api/programs/[programId]/payouts/count/route.ts`, `/api/programs/[programId]/payouts/route.ts` | Refactored to derive `programId` from workspace context instead of route params; removed explicit `programId` extraction and validation; updated query logic accordingly.                                                                                                                |
| `apps/web/lib/actions/partners/program-resources/add-program-resource.ts`, `/delete-program-resource.ts`, `/upload-lander-image.ts` | Removed `programId` from input schemas and action handlers; now internally derives `programId` from workspace context in all partner resource actions.                                                                                                                                                                          |
| `apps/web/lib/swr/use-commissions-timeseries.ts`, `/use-discount-partners.ts`, `/use-discounts.ts`, `/use-payouts-count.ts`, `/use-payouts.ts`, `/use-program-metrics.ts`, `/use-program-resources.ts`, `/use-program-revenue.ts`, `/use-program.ts`, `/use-reward-partners.ts`, `/use-rewards.ts` | Refactored SWR hooks to no longer use `programId` from URL params; now use `defaultProgramId` from `useWorkspace`; updated fetch keys and conditional logic; removed `useParams` imports.                                                         |
| `apps/web/lib/swr/use-partners-count.ts`                                                                               | Removed `programId` from parameters and internal logic; simplified SWR key and query string construction; updated function signature.                                                                                                                                                                                          |
| `apps/web/ui/layout/sidebar/app-sidebar-nav.tsx`                                                                       | Updated all program-related sidebar links to use `/program` instead of `/programs/${defaultProgramId}`; adjusted logic for active path detection.                                                                                                                                                                              |
| `apps/web/ui/partners/archive-partner-modal.tsx`, `/ban-partner-modal.tsx`, `/design/branding-form.tsx`, `/mark-commission-duplicate-modal.tsx`, `/mark-commission-fraud-or-canceled-modal.tsx`, `/mark-payout-paid-modal.tsx`, `/payout-details-sheet.tsx`, `/unban-partner-modal.tsx` | Removed `useParams` and `programId` usage; now rely on `useWorkspace` for workspace and program context; updated URLs and conditional checks accordingly.                                                                                                                               |
| `apps/web/ui/partners/partner-details-sheet.tsx`, `/partner-row-item.tsx`                                              | Simplified URLs in tabs and links by removing dynamic `programId` segments; updated to use `/program/` paths.                                                                                                                                                                                                                  |
| `apps/web/ui/partners/design/modals/earnings-calculator-block-modal.tsx`                                               | Updated link URLs to remove dynamic `defaultProgramId` segment, using `/program/settings/rewards` instead.                                                                                                                                                                                                                     |
| `apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/customers/[customerId]/page-client.tsx`, `/program/branding/program-branding-tabs.tsx`, `/program/branding/resources/add-color-modal.tsx`, `/add-file-modal.tsx`, `/add-logo-modal.tsx`, `/resources/page-client.tsx`, `/commissions/commission-stats.tsx`, `/commissions/commission-table.tsx`, `/page-client.tsx`, `/partners/partner-stats.tsx`, `/partners/partner-table.tsx`, `/payouts/payout-table.tsx`, `/pending-payouts.tsx`, `/program-metrics.tsx`, `/settings/layout.tsx`, `/settings/program-settings-header.tsx`, `/top-partners.tsx` | Removed `programId` from URL params, hooks, and links; updated all affected routes and navigation to use `/program` instead of `/programs/${programId}`; refactored components to derive necessary context internally.                            |
| `apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/page.tsx`                                                    | Deleted file; previously handled redirect logic based on project and program configuration.                                                                                                                                                                                                                                    |
| `apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/plan-usage.tsx`                                      | Updated conditions and links for partners-related usage categories to use `/program` path and require both `partnersEnabled` and `defaultProgramId`.                                                                                                                                    |
| `apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/resources/page-client.tsx`             | Removed `useParams` usage; `useProgramResources` now called without arguments.                                                                                                                                                                                                           |
| `apps/web/app/(ee)/app.dub.co/(new-program)/sidebar-context.tsx`                                                       | Changed redirect logic to use `/program` path instead of `/programs/${defaultProgramId}`.                                                                                                                                                                                               |
| `apps/web/lib/middleware/utils/app-redirect.ts`                                                                        | Updated redirect patterns to replace plural "programs" with singular "program"; removed dynamic program ID segments from all redirect rules.                                                                                                                                            |
| `apps/web/lib/swr/use-program-resources.ts`                                                                            | Refactored hook to take no parameters; now determines endpoint internally using `useParams` and `useWorkspace`.                                                                                                                                                                         |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant UI
    participant useWorkspace
    participant API/Actions

    UI->>useWorkspace: Get workspaceId, defaultProgramId
    useWorkspace-->>UI: Returns context (workspaceId, defaultProgramId)
    UI->>API/Actions: Make request (no explicit programId param)
    API/Actions->>useWorkspace: Get workspace context
    API/Actions->>API/Actions: Derive programId via getDefaultProgramIdOrThrow(workspace)
    API/Actions-->>UI: Respond with data

Possibly related PRs

  • Add archive partner functionality #2497: Modifies filtering logic in the partner count route and adds archive partner functionality; related due to changes in partner counting logic and the same API route file.

Poem

Hopping down the codebase trail,
The rabbit found IDs gone stale—
No more programId to pass or seek,
All is context now, so clean and sleek!
URLs are short, the routes refined,
With /program paths so well-aligned.
🐇 Cheers to code that’s less entwined!


<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 8490f272b2530b1e2689af3fae2f0f19e94db9ca and 378c9c110788591c4d7d4d2a1f1b690db64e66c9.

</details>

<details>
<summary>📒 Files selected for processing (6)</summary>

* `apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/customers/[customerId]/page-client.tsx` (2 hunks)
* `apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/import-export-buttons.tsx` (1 hunks)
* `apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/invite-partner-sheet.tsx` (1 hunks)
* `apps/web/lib/actions/partners/create-program.ts` (1 hunks)
* `apps/web/ui/links/link-builder/link-partner-details.tsx` (1 hunks)
* `apps/web/ui/modals/import-rewardful-modal.tsx` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (3)</summary>

* apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/invite-partner-sheet.tsx
* apps/web/ui/modals/import-rewardful-modal.tsx
* apps/web/ui/links/link-builder/link-partner-details.tsx

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/customers/[customerId]/page-client.tsx

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: build

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>apps/web/lib/actions/partners/create-program.ts (1)</summary>

`184-184`: **LGTM! Redirect path correctly simplified.**

The change from `/programs/${program.id}` to `/program` is consistent with the broader refactor to remove explicit program ID dependencies. Since the newly created program is set as the workspace's `defaultProgramId` (line 112), the target route can derive the program context from the workspace.

</details>
<details>
<summary>apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/import-export-buttons.tsx (1)</summary>

`36-36`: **LGTM! Navigation path correctly simplified.**

The change from `/programs/${program?.id}/partners` to `/program/partners` is consistent with the broader refactor. This removes the dependency on explicit program ID in the URL and leverages the workspace context instead. The optional chaining on `program?.id` in the old code suggests this approach is more reliable.

</details>

</blockquote></details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=dubinc/dub&utm_content=2498):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (2)
apps/web/lib/actions/partners/upload-lander-image.ts (1)

9-12: 🛠️ Refactor suggestion

Remove unused programId from the schema.

The schema still requires programId as input, but the action no longer uses it (line 18 derives it from workspace context instead). This creates confusion and unnecessary coupling.

const schema = z.object({
  workspaceId: z.string(),
-  programId: z.string(),
});
apps/web/app/(ee)/api/programs/[programId]/payouts/route.ts (1)

1-14: 💡 Verification agent

🧩 Analysis chain

Verify route path consistency with the refactored implementation.

The file path still includes [programId] as a dynamic route segment, but the handler no longer uses this parameter. Consider whether the route should be updated to reflect that programId is no longer required from the URL.


🏁 Script executed:

#!/bin/bash
# Check if other API routes in the same pattern have been updated
fd -t f "route.ts" apps/web/app | grep -E "programs/\[programId\]" | head -10

Length of output: 872


Remove the unused [programId] segment from the payouts route

Your GET handler now sources the program ID via getDefaultProgramIdOrThrow(workspace) (and doesn’t read params.programId), so the [programId] folder is misleading. You should either:

  • Drop the dynamic segment—move
    apps/web/app/(ee)/api/programs/[programId]/payouts/route.ts

    apps/web/app/(ee)/api/programs/payouts/route.ts
    and update any client calls/tests.
  • Or re-introduce params.programId into your handler if the URL must drive which program is used.

Points to address:

  • File/folder structure under apps/web/app/(ee)/api/programs
  • Downstream client code (and any tests) referencing this endpoint
🧹 Nitpick comments (4)
apps/web/lib/swr/use-commissions-timeseries.ts (1)

43-43: Simplify the boolean expression.

The ternary operator is unnecessary here. The expression can be simplified for better readability.

-    loading: !data && !error ? true : false,
+    loading: !data && !error,
🧰 Tools
🪛 Biome (1.9.4)

[error] 43-43: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apps/web/lib/swr/use-program.ts (1)

35-35: Simplify the loading state logic.

The ternary operator with boolean literals is unnecessary and can be simplified.

Apply this diff to simplify the loading state:

-    loading: !program && !error ? true : false,
+    loading: !program && !error,
🧰 Tools
🪛 Biome (1.9.4)

[error] 35-35: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apps/web/lib/swr/use-program-revenue.ts (1)

43-43: Simplify the ternary operator.

The boolean literal in the ternary expression is unnecessary and can be simplified.

-    loading: !data && !error ? true : false,
+    loading: !data && !error,
🧰 Tools
🪛 Biome (1.9.4)

[error] 43-43: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apps/web/lib/swr/use-program-resources.ts (1)

14-18: Consider simplifying the endpoint construction logic.

The endpoint construction logic handles multiple scenarios but could be made more readable and maintainable.

Consider extracting the endpoint logic into a helper function or adding comments to clarify the different scenarios:

+ // Determine the appropriate endpoint based on context:
+ // 1. Partner-facing view: use programSlug from URL
+ // 2. Admin view: use defaultProgramId from workspace
+ // 3. No program context: disable request
  const endpoint = programSlug
    ? `/api/partner-profile/programs/${programSlug}/resources`
    : defaultProgramId
      ? `/api/programs/${defaultProgramId}/resources?workspaceId=${workspaceId}`
      : null;

Alternatively, extract to a helper function:

const getResourcesEndpoint = (programSlug: string | undefined, defaultProgramId: string | undefined, workspaceId: string) => {
  if (programSlug) return `/api/partner-profile/programs/${programSlug}/resources`;
  if (defaultProgramId) return `/api/programs/${defaultProgramId}/resources?workspaceId=${workspaceId}`;
  return null;
};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 54f7510 and 5d86d1e.

📒 Files selected for processing (31)
  • apps/web/app/(ee)/api/partners/count/route.ts (2 hunks)
  • apps/web/app/(ee)/api/programs/[programId]/payouts/count/route.ts (2 hunks)
  • apps/web/app/(ee)/api/programs/[programId]/payouts/route.ts (2 hunks)
  • apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/resources/page-client.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/branding/resources/add-color-modal.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/branding/resources/add-file-modal.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/branding/resources/add-logo-modal.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/branding/resources/page-client.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/commissions/commission-table.tsx (0 hunks)
  • apps/web/lib/actions/partners/program-resources/add-program-resource.ts (2 hunks)
  • apps/web/lib/actions/partners/program-resources/delete-program-resource.ts (2 hunks)
  • apps/web/lib/actions/partners/upload-lander-image.ts (2 hunks)
  • apps/web/lib/swr/use-commissions-timeseries.ts (1 hunks)
  • apps/web/lib/swr/use-discount-partners.ts (1 hunks)
  • apps/web/lib/swr/use-discounts.ts (1 hunks)
  • apps/web/lib/swr/use-payouts-count.ts (1 hunks)
  • apps/web/lib/swr/use-payouts.ts (1 hunks)
  • apps/web/lib/swr/use-program-metrics.ts (1 hunks)
  • apps/web/lib/swr/use-program-resources.ts (2 hunks)
  • apps/web/lib/swr/use-program-revenue.ts (3 hunks)
  • apps/web/lib/swr/use-program.ts (2 hunks)
  • apps/web/lib/swr/use-reward-partners.ts (1 hunks)
  • apps/web/lib/swr/use-rewards.ts (1 hunks)
  • apps/web/ui/partners/archive-partner-modal.tsx (2 hunks)
  • apps/web/ui/partners/ban-partner-modal.tsx (2 hunks)
  • apps/web/ui/partners/design/branding-form.tsx (2 hunks)
  • apps/web/ui/partners/mark-commission-duplicate-modal.tsx (3 hunks)
  • apps/web/ui/partners/mark-commission-fraud-or-canceled-modal.tsx (3 hunks)
  • apps/web/ui/partners/mark-payout-paid-modal.tsx (1 hunks)
  • apps/web/ui/partners/payout-details-sheet.tsx (3 hunks)
  • apps/web/ui/partners/unban-partner-modal.tsx (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/commissions/commission-table.tsx
🧰 Additional context used
🧬 Code Graph Analysis (12)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/branding/resources/add-logo-modal.tsx (1)
apps/web/lib/swr/use-program-resources.ts (1)
  • useProgramResources (10-38)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/branding/resources/add-file-modal.tsx (1)
apps/web/lib/swr/use-program-resources.ts (1)
  • useProgramResources (10-38)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/branding/resources/page-client.tsx (1)
apps/web/lib/swr/use-program-resources.ts (1)
  • useProgramResources (10-38)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/branding/resources/add-color-modal.tsx (1)
apps/web/lib/swr/use-program-resources.ts (1)
  • useProgramResources (10-38)
apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/resources/page-client.tsx (1)
apps/web/lib/swr/use-program-resources.ts (1)
  • useProgramResources (10-38)
apps/web/lib/swr/use-payouts-count.ts (1)
apps/web/lib/types.ts (1)
  • PayoutsCount (424-428)
apps/web/ui/partners/mark-payout-paid-modal.tsx (1)
apps/web/lib/actions/partners/mark-payout-paid.ts (1)
  • markPayoutPaidAction (14-46)
apps/web/app/(ee)/api/partners/count/route.ts (1)
apps/web/lib/api/programs/get-default-program-id-or-throw.ts (1)
  • getDefaultProgramIdOrThrow (4-17)
apps/web/lib/actions/partners/program-resources/add-program-resource.ts (1)
apps/web/lib/api/programs/get-default-program-id-or-throw.ts (1)
  • getDefaultProgramIdOrThrow (4-17)
apps/web/lib/swr/use-discount-partners.ts (1)
apps/web/lib/types.ts (1)
  • EnrolledPartnerProps (402-404)
apps/web/lib/actions/partners/upload-lander-image.ts (1)
apps/web/lib/api/programs/get-default-program-id-or-throw.ts (1)
  • getDefaultProgramIdOrThrow (4-17)
apps/web/lib/actions/partners/program-resources/delete-program-resource.ts (1)
apps/web/lib/api/programs/get-default-program-id-or-throw.ts (1)
  • getDefaultProgramIdOrThrow (4-17)
🪛 Biome (1.9.4)
apps/web/lib/swr/use-commissions-timeseries.ts

[error] 43-43: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apps/web/lib/swr/use-program.ts

[error] 35-35: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apps/web/lib/swr/use-program-revenue.ts

[error] 43-43: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (53)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/branding/resources/add-color-modal.tsx (2)

49-49: LGTM! Hook refactor correctly implemented.

The useProgramResources hook now internally determines the program ID using workspace context, eliminating the need to pass it as a parameter.


107-112: LGTM! Action call correctly updated.

The executeAsync call correctly removes the programId parameter since the action now derives it internally via getDefaultProgramIdOrThrow(workspace).

apps/web/ui/partners/design/branding-form.tsx (2)

41-41: LGTM! Workspace context integration correctly implemented.

Using defaultProgramId from useWorkspace() instead of extracting programId from URL parameters aligns perfectly with the refactor objectives.


52-52: LGTM! LocalStorage key correctly updated.

The localStorage key now uses defaultProgramId to maintain consistency with the program identification approach.

apps/web/ui/partners/payout-details-sheet.tsx (2)

40-40: LGTM! Workspace context integration correctly implemented.

Using defaultProgramId from useWorkspace() instead of extracting programId from URL parameters successfully removes the dependency on route parameters.


63-63: LGTM! URL constructions correctly updated.

The partner details and commissions links now use defaultProgramId from workspace context, maintaining functionality while removing URL parameter dependencies.

Also applies to: 186-186

apps/web/ui/partners/mark-payout-paid-modal.tsx (2)

38-38: LGTM: Correctly using workspace context for program identification.

The change from extracting programId via useParams() to using defaultProgramId from useWorkspace() aligns perfectly with the server-side markPayoutPaidAction which derives the program ID internally via getDefaultProgramIdOrThrow(workspace).


46-46: LGTM: Consistent use of defaultProgramId in cache invalidation.

The mutation cache key correctly uses defaultProgramId to maintain consistency with the new workspace-based program identification pattern.

apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/resources/page-client.tsx (1)

14-14: LGTM: Simplified hook usage aligns with internal program ID resolution.

The removal of parameters from useProgramResources() is correct. The hook now internally handles program identification by checking for programSlug from route parameters or falling back to defaultProgramId from workspace context, as shown in the relevant code snippet from use-program-resources.ts.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/branding/resources/add-file-modal.tsx (1)

47-47: LGTM: Correctly simplified to use internal program identification.

The removal of parameters from useProgramResources() is consistent with the hook's refactored implementation that internally resolves the program context using useParams() and useWorkspace(), as shown in the relevant code snippet.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/branding/resources/add-logo-modal.tsx (1)

47-47: LGTM: Consistent with the centralized program identification pattern.

The simplification of useProgramResources() call without parameters correctly leverages the hook's internal logic for program context resolution, maintaining consistency with the broader refactoring across all resource management components.

apps/web/ui/partners/archive-partner-modal.tsx (2)

26-26: Good architectural improvement: centralizing program ID management.

The change from URL parameters to workspace context is a clean refactor that simplifies the component API and centralizes program ID management.


46-54: Correctly updated conditional logic and dependency array.

The removal of programId from the conditional check and dependency array is consistent with the refactor. The component now properly relies on workspaceId from the workspace context.

apps/web/ui/partners/mark-commission-duplicate-modal.tsx (3)

37-37: Proper workspace context integration.

Good use of workspace context to obtain both workspaceId and defaultProgramId, eliminating dependency on URL parameters.


46-46: Correctly using defaultProgramId in mutation path.

The mutation path now properly uses defaultProgramId from workspace context instead of URL parameters, which is consistent with the architectural refactor.


148-148: Simplified conditional logic.

Removing the programId check simplifies the validation logic since the program ID is now managed internally through workspace context.

apps/web/ui/partners/ban-partner-modal.tsx (2)

65-75: Consistent refactor in onSubmit callback.

The removal of programId from the conditional check and dependency array is consistent with the workspace context refactor. The logic now properly relies on workspaceId.


80-82: Properly updated isDisabled memo.

The isDisabled memoization correctly removes programId dependency and includes workspaceId, maintaining consistency with the architectural changes.

apps/web/ui/partners/unban-partner-modal.tsx (2)

58-66: Consistent refactor pattern in onSubmit.

The changes mirror the pattern used in other partner modal components - removing programId dependency and properly updating the dependency array with workspaceId.


70-72: Correctly updated isDisabled logic.

The isDisabled memoization follows the same pattern as the ban-partner-modal, ensuring consistency across related components in the refactor.

apps/web/lib/swr/use-program.ts (1)

14-14: LGTM! Clean refactoring to use workspace context.

The change from useParams() to useWorkspace() for program identification is consistent with the PR objective and centralizes program ID resolution through workspace context rather than URL parameters.

Also applies to: 21-23

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/branding/resources/page-client.tsx (2)

20-20: LGTM! Consistent with the internal program identification pattern.

The removal of programId parameter from useProgramResources() is correct, as the hook now derives the program ID internally from workspace context as shown in the relevant code snippet from apps/web/lib/swr/use-program-resources.ts.


41-45: LGTM! Properly updated action call parameters.

The removal of programId from the executeAsync call is consistent with the refactoring where actions now derive the program ID internally from workspace context.

apps/web/lib/swr/use-reward-partners.ts (2)

17-17: LGTM! Consistent refactoring pattern.

The change from useParams() to useWorkspace() follows the established pattern for centralizing program identification through workspace context.


20-26: LGTM! Properly updated SWR key and endpoint construction.

The SWR condition now correctly checks for defaultProgramId instead of programId, and the endpoint URL construction uses the workspace-derived program ID. This ensures the hook only fetches data when all required identifiers are available.

apps/web/ui/partners/mark-commission-fraud-or-canceled-modal.tsx (3)

44-44: LGTM! Consistent workspace context usage.

The change from useParams() to useWorkspace() aligns with the refactoring pattern and ensures program identification is centralized through workspace context.


53-53: LGTM! Properly updated cache invalidation.

The mutate prefix correctly uses defaultProgramId to ensure cache invalidation targets the correct program endpoint after the commission status update.


156-156: LGTM! Simplified conditional logic.

The conditional check is now simplified to only verify workspaceId since defaultProgramId is derived from the workspace context and doesn't need separate validation.

apps/web/lib/swr/use-discounts.ts (1)

7-12: LGTM! Consistent refactoring to use workspace context.

The hook correctly replaces URL parameter extraction with workspace context. The conditional logic properly ensures both workspaceId and defaultProgramId are available before making the API request.

apps/web/lib/swr/use-payouts-count.ts (1)

12-18: LGTM! Follows the consistent refactoring pattern.

The hook properly implements the same refactoring approach as other hooks, removing URL parameter dependency and using workspace context for program identification.

apps/web/lib/swr/use-program-revenue.ts (1)

15-15: LGTM! Consistent workspace context usage.

The refactoring correctly implements the same pattern as other hooks, using defaultProgramId from workspace context instead of URL parameters.

Also applies to: 31-32

apps/web/lib/swr/use-rewards.ts (1)

7-12: LGTM! Consistent implementation of the refactoring pattern.

The hook correctly follows the same pattern as other hooks in this PR, using workspace context instead of URL parameters for program identification.

apps/web/lib/swr/use-payouts.ts (2)

13-13: LGTM! Proper refactoring to use workspace context.

The change from useParams to useWorkspace correctly centralizes program ID management through workspace context, aligning with the PR objectives to remove dependencies on URL parameters.


16-21: Good defensive programming with conditional SWR key.

The conditional logic ensures SWR only attempts to fetch when both workspaceId and defaultProgramId are available, preventing unnecessary API calls and potential errors. This is a solid improvement over the previous implementation.

apps/web/lib/swr/use-discount-partners.ts (2)

18-18: Consistent refactoring pattern applied correctly.

The change to use defaultProgramId from useWorkspace instead of URL parameters is consistent with the overall refactoring effort and correctly implemented.


21-27: Well-structured conditional SWR key with multiple guards.

The conditional logic properly combines the enabled parameter with the availability of both IDs, providing fine-grained control over when the API call should be made. This prevents unnecessary requests and improves performance.

apps/web/lib/swr/use-program-metrics.ts (2)

8-8: Appropriate use of workspace context for program identification.

The refactoring correctly uses useWorkspace to obtain both workspace and program identifiers, eliminating the dependency on URL parameters as intended.


12-16: Proper conditional fetching logic implemented.

The SWR key construction correctly ensures both workspaceId and defaultProgramId are available before attempting the API call, following the established pattern from other hooks in this refactor.

apps/web/lib/actions/partners/program-resources/delete-program-resource.ts (3)

3-3: Correct import for centralized program ID resolution.

The import of getDefaultProgramIdOrThrow aligns with the refactoring pattern to derive program IDs internally rather than from client input.


15-19: Schema correctly updated to remove programId dependency.

Removing programId from the input schema is appropriate as the program ID is now derived internally from workspace context, preventing clients from providing potentially incorrect or unauthorized program IDs.


25-26: Proper internal derivation of program ID with error handling.

The use of getDefaultProgramIdOrThrow(workspace) correctly centralizes program ID resolution and provides appropriate error handling when no default program exists, as shown in the relevant code snippet from apps/web/lib/api/programs/get-default-program-id-or-throw.ts (lines 4-17).

apps/web/lib/actions/partners/upload-lander-image.ts (1)

16-18: LGTM: Clean implementation of workspace-derived program ID.

The refactor correctly derives the program ID from workspace context, eliminating the dependency on external input parameters.

apps/web/lib/actions/partners/program-resources/add-program-resource.ts (2)

4-4: LGTM: Clean import addition.

The import is correctly added to support the workspace-derived program ID pattern.


54-55: LGTM: Consistent implementation of workspace-derived program ID.

The refactor correctly removes programId from the input destructuring and derives it from workspace context instead. This is consistent with the broader refactoring pattern.

apps/web/app/(ee)/api/partners/count/route.ts (2)

1-1: LGTM: Appropriate import for workspace-derived program ID.

The import correctly supports the refactoring to derive program ID from workspace context.


11-11: LGTM: Clean removal of programId dependency.

The refactor correctly derives program ID from workspace context instead of requiring it as a query parameter, simplifying the API interface.

apps/web/app/(ee)/api/programs/[programId]/payouts/route.ts (1)

13-14: LGTM: Correct implementation of workspace-derived program ID.

The refactor properly removes dependency on the programId route parameter and derives it from workspace context instead.

apps/web/app/(ee)/api/programs/[programId]/payouts/count/route.ts (3)

1-1: LGTM: Clean import addition for centralized program ID resolution.

The import of getDefaultProgramIdOrThrow aligns with the refactor to derive program IDs from workspace context rather than route parameters.


13-75: LGTM: Core logic preserved with improved program ID resolution.

The refactor correctly maintains all existing functionality while centralizing program ID resolution. The query building, filtering logic, and response formatting remain intact and correct.


10-11:

Details

❓ Verification inconclusive

Verify route path consistency with the refactor.

The function signature correctly removes the params argument and derives programId internally. However, the route path still contains [programId] but no longer uses it from the route parameters.

Please verify if the route path should be updated to reflect that programId is no longer extracted from URL parameters:

Consider updating the route path to /api/programs/payouts/count since the programId is now derived from workspace context.


🏁 Script executed:

#!/bin/bash
# Check if there are other API routes that have been similarly refactored
rg -A 5 "export const GET = withWorkspace.*getDefaultProgramIdOrThrow" --type ts

Length of output: 82


Verify dynamic route path vs. internal programId resolution

The GET handler now derives programId via getDefaultProgramIdOrThrow(workspace) and no longer reads it from URL params, but the folder name still includes [programId]. Ensure this dynamic segment is still needed—if all routes now pull programId from the workspace, you should remove the [programId] folder and update the path accordingly (e.g. /api/programs/payouts/count).

• Search for other handlers that use getDefaultProgramIdOrThrow to confirm consistency:

#!/bin/bash
rg "getDefaultProgramIdOrThrow" -n .

• If no other routes rely on the URL param, refactor:

  • Remove or rename the [programId] directory under apps/web/app/(ee)/api/programs/
  • Update any import or link paths accordingly
apps/web/lib/swr/use-program-resources.ts (3)

2-2: LGTM: Proper imports for internal dependency resolution.

The addition of useParams and useWorkspace correctly enables the hook to derive its dependencies internally rather than accepting them as parameters.

Also applies to: 6-6


10-12: LGTM: Clean function signature simplification.

Removing the parameter dependency and deriving values internally aligns well with the broader refactor pattern across the codebase.


36-36: LGTM: Simplified loading state logic.

The simplified isLoading logic correctly removes dependency on input props and maintains the same behavior.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/settings/layout.tsx (1)

6-9: Clean up unused parameter in function signature.

The programId parameter is no longer used since ProgramSettingsHeader now gets the slug internally via useParams(). Consider removing it from the function signature.

export default function ProgramSettingsLayout({
  children,
  params,
-}: PropsWithChildren<{ params: { slug: string; programId: string } }>) {
+}: PropsWithChildren<{ params: { slug: string } }>) {
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/program-branding-tabs.tsx (1)

8-8: Remove unused programId parameter.

The programId parameter is no longer used in the component since URLs have been simplified to use /program/... paths instead of /programs/${programId}/.... Consider removing it from the component props.

export function ProgramBrandingTabs({
  slug,
-  programId,
}: {
  slug: string;
-  programId: string;
}) {
apps/web/ui/layout/sidebar/app-sidebar-nav.tsx (1)

256-256: Simplify the unnecessary ternary operator.

The boolean condition can be simplified for better readability.

-        showNews: pathname.startsWith(`/${slug}/program`) ? false : true,
+        showNews: !pathname.startsWith(`/${slug}/program`),
🧰 Tools
🪛 Biome (1.9.4)

[error] 256-256: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

apps/web/lib/swr/use-partners-count.ts (1)

14-14: Consider removing unused programId parameter.

The programId parameter in the function signature is no longer used in the implementation and could be removed for clarity.

} & {
-  programId?: string;
  ignoreParams?: boolean;
  enabled?: boolean;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f24b2c and fe0a611.

📒 Files selected for processing (28)
  • apps/web/app/(ee)/app.dub.co/(new-program)/sidebar-context.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/customers/[customerId]/page-client.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/program-branding-tabs.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/resources/add-color-modal.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/resources/add-file-modal.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/resources/add-logo-modal.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/resources/page-client.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-stats.tsx (2 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-table.tsx (0 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/page-client.tsx (3 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partner-stats.tsx (2 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partner-table.tsx (2 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/payout-table.tsx (2 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/pending-payouts.tsx (2 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/program-metrics.tsx (2 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/settings/layout.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/settings/program-settings-header.tsx (2 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/top-partners.tsx (2 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/page.tsx (0 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/plan-usage.tsx (1 hunks)
  • apps/web/lib/middleware/utils/app-redirect.ts (1 hunks)
  • apps/web/lib/swr/use-partners-count.ts (1 hunks)
  • apps/web/ui/layout/sidebar/app-sidebar-nav.tsx (2 hunks)
  • apps/web/ui/modals/program-welcome-modal.tsx (1 hunks)
  • apps/web/ui/partners/design/modals/earnings-calculator-block-modal.tsx (2 hunks)
  • apps/web/ui/partners/partner-details-sheet.tsx (4 hunks)
  • apps/web/ui/partners/partner-row-item.tsx (2 hunks)
  • apps/web/ui/partners/payout-details-sheet.tsx (2 hunks)
💤 Files with no reviewable changes (2)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-table.tsx
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/page.tsx
✅ Files skipped from review due to trivial changes (1)
  • apps/web/ui/partners/payout-details-sheet.tsx
🧰 Additional context used
🧬 Code Graph Analysis (6)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/settings/layout.tsx (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/settings/program-settings-header.tsx (1)
  • ProgramSettingsHeader (6-43)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/resources/add-logo-modal.tsx (1)
apps/web/lib/swr/use-program-resources.ts (1)
  • useProgramResources (10-38)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/pending-payouts.tsx (1)
apps/web/lib/types.ts (1)
  • PayoutResponse (432-432)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/resources/add-color-modal.tsx (1)
apps/web/lib/swr/use-program-resources.ts (1)
  • useProgramResources (10-38)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/resources/page-client.tsx (1)
apps/web/lib/swr/use-program-resources.ts (1)
  • useProgramResources (10-38)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/resources/add-file-modal.tsx (1)
apps/web/lib/swr/use-program-resources.ts (1)
  • useProgramResources (10-38)
🪛 Biome (1.9.4)
apps/web/ui/layout/sidebar/app-sidebar-nav.tsx

[error] 256-256: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (40)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/settings/layout.tsx (1)

13-13: LGTM! Simplified component usage.

The refactor to remove explicit prop passing is consistent with the broader effort to simplify routing and parameter handling.

apps/web/app/(ee)/app.dub.co/(new-program)/sidebar-context.tsx (1)

37-39: LGTM! Simplified routing structure.

The change from /programs/${defaultProgramId} to /program aligns with the broader refactor to remove explicit programId parameters from URLs while maintaining the same functionality.

apps/web/ui/partners/design/modals/earnings-calculator-block-modal.tsx (2)

46-46: LGTM! Consistent workspace hook usage.

Removing the defaultProgramId extraction aligns with the refactor to derive program information from context rather than explicit parameters.


131-131: LGTM! Updated link path structure.

The URL change from /programs/${defaultProgramId} to /program maintains functionality while simplifying the routing structure.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/payouts/payout-table.tsx (2)

302-302: LGTM! Simplified parameter extraction.

Removing the programId extraction is consistent with the refactor to use program information from workspace context instead of URL parameters.


318-318: LGTM! Updated tooltip link path.

The URL change maintains the same functionality while using the simplified /program path structure.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/resources/page-client.tsx (1)

20-20: LGTM: Simplified hook usage aligns with centralized program identification.

The refactored useProgramResources() hook now handles program identification internally, eliminating the need to pass explicit parameters. This simplifies the component logic and aligns with the broader effort to centralize program context within workspace hooks.

apps/web/ui/modals/program-welcome-modal.tsx (2)

23-23: LGTM: Simplified parameter extraction aligns with refactor.

Removing programId from URL parameters is consistent with the broader refactor to centralize program identification within workspace context.


31-31: LGTM: Simplified URL structure removes dependency on dynamic program ID.

The URL path change from /programs/${programId}/branding to /program/branding aligns with the new routing structure that uses workspace context for program identification instead of explicit URL parameters.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partner-stats.tsx (2)

16-16: LGTM: Parameter extraction simplified to remove programId dependency.

Removing programId from URL parameters is consistent with the refactor to centralize program identification within workspace context.


40-40: LGTM: URL structure simplified to use singular program route.

The URL change from /programs/${programId}/partners to /program/partners aligns with the new routing structure that eliminates dynamic program ID segments in favor of workspace-based program context.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-stats.tsx (2)

11-11: LGTM: Parameter extraction simplified to remove programId dependency.

Removing programId from URL parameters is consistent with the refactor to centralize program identification within workspace context.


21-21: LGTM: URL structure simplified to use singular program route.

The URL change from /programs/${programId}/commissions to /program/commissions aligns with the new routing structure that eliminates dynamic program ID segments in favor of workspace-based program context.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/resources/add-logo-modal.tsx (1)

47-47: LGTM: Clean API simplification.

The change correctly removes explicit parameter passing to useProgramResources(), which now internally derives the program information via useParams and useWorkspace. This aligns with the broader refactor to centralize program identification.

apps/web/ui/partners/partner-row-item.tsx (2)

18-18: Consistent with URL structure refactor.

Correctly removes programId from route parameters as it's no longer needed in the simplified routing structure.


73-73: URL path correctly updated.

The href change from /programs/${programId}/partners to /program/partners aligns with the broader refactor to use fixed program paths instead of dynamic segments.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/customers/[customerId]/page-client.tsx (1)

241-241: URL structure correctly simplified.

The viewAllHref path change from /programs/${programId}/commissions to /program/commissions is consistent with the architectural decision to remove dynamic program ID segments from URLs.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/top-partners.tsx (2)

8-8: Consistent parameter cleanup.

Correctly removes programId from useParams() destructuring as it's no longer needed with the new routing structure.


20-20: URL path correctly updated to match new structure.

The href change from /programs/${programId}/partners to /program/partners completes the consistent URL structure refactor across all reviewed components.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/program-branding-tabs.tsx (1)

26-26: LGTM! URL simplification is consistent with the refactor.

The URLs have been correctly simplified from /programs/${programId}/branding to /program/branding and similar for resources, which aligns with the broader refactor to remove explicit programId from URL parameters.

Also applies to: 31-31

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/page-client.tsx (2)

17-17: LGTM! Correctly removed programId extraction.

The removal of programId from useParams() is appropriate since the program context is now derived internally from the workspace context rather than URL parameters.


32-32: URL paths simplified correctly.

The URLs have been appropriately updated from /programs/${programId}/settings and /programs/${programId}/commissions to /program/settings and /program/commissions, removing the dynamic program ID segment as intended.

Also applies to: 76-76

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/billing/plan-usage.tsx (2)

200-200: LGTM! Improved conditional logic.

Adding the defaultProgramId check to the condition is appropriate - partner-related usage categories should only be shown when both partners are enabled and a default program ID exists in the workspace context.


207-207: URL paths correctly simplified.

The partner-related URLs have been properly updated from /programs/${defaultProgramId}/partners and /programs/${defaultProgramId}/payouts to /program/partners and /program/payouts, aligning with the refactor to remove explicit program ID segments.

Also applies to: 215-215

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/resources/add-color-modal.tsx (1)

49-49: LGTM! Hook usage updated correctly.

The useProgramResources() hook call has been correctly updated to not pass any parameters, which aligns with the refactored hook implementation that now derives the program ID internally from the workspace context (as shown in the apps/web/lib/swr/use-program-resources.ts snippet).

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/pending-payouts.tsx (1)

12-12: LGTM! Clean refactor implementation.

The changes correctly implement the programId removal refactor:

  • Proper use of defaultProgramId from workspace context instead of URL parameters
  • Appropriate conditional checks in SWR to prevent unnecessary API calls
  • Consistent URL path simplification

Also applies to: 15-22, 36-36

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/partner-table.tsx (1)

353-353: LGTM! Consistent with the routing refactor.

The changes correctly remove programId dependency and use the simplified routing structure. The commission navigation will work properly with the new /program/commissions path.

Also applies to: 455-455

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/branding/resources/add-file-modal.tsx (1)

47-47: LGTM! Properly adapted to refactored dependencies.

The changes correctly reflect the updated useProgramResources hook and addProgramResourceAction that now internally handle programId via workspace context. The simplified API calls are consistent with the broader refactor.

Also applies to: 92-98

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/program-metrics.tsx (2)

62-62: LGTM! URL refactor implemented correctly.

The parameter and URL path changes are consistent with the broader refactor to remove programId dependencies and use simplified routing.

Also applies to: 67-67


23-23: Clarify the sales tab mapping intention.

The TODO comment suggests uncertainty about the correct tab for the "Sales" metric. Currently, both the "Sales" and "Commissions" stats point to the "commissions" tab. Please confirm:

  1. Is this the intended behavior temporarily?
  2. When will the sales analytics tab be available?
  3. Should these stats point to different destinations?

Also applies to: 31-31

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/settings/program-settings-header.tsx (2)

6-7: LGTM! Clean refactor to remove programId dependency.

The component now correctly uses useParams to get the slug directly instead of relying on props, which is more appropriate for a client component.


20-20: Consistent URL simplification across all tabs.

All tab URLs have been correctly updated to use the simplified /program/settings/ pattern, removing the programId dependency as intended.

Also applies to: 25-25, 30-30, 35-35

apps/web/ui/partners/partner-details-sheet.tsx (2)

41-41: Correct removal of defaultProgramId dependency.

The components no longer need to destructure defaultProgramId from useWorkspace since program context is now handled internally by the API endpoints.

Also applies to: 217-217


169-169: URL paths consistently simplified to use /program route.

All partner-related URLs have been correctly updated to use the simplified /program/ pattern instead of /programs/${programId}/, aligning with the broader routing refactor.

Also applies to: 261-261, 278-278

apps/web/ui/layout/sidebar/app-sidebar-nav.tsx (1)

74-74: Sidebar navigation URLs correctly updated to use simplified /program route.

All program-related navigation items now use the unified /program/ path pattern, removing the dynamic programId segment as intended.

Also applies to: 78-78, 83-83, 87-87, 91-91, 95-95, 99-99

apps/web/lib/swr/use-partners-count.ts (1)

38-38: SWR key correctly simplified to remove programId dependency.

The condition now appropriately checks only the enabled flag, aligning with the API endpoint changes that handle program identification internally.

apps/web/lib/middleware/utils/app-redirect.ts (4)

24-27: LGTM! Correctly handles legacy URL migration.

The regex pattern properly captures the workspace slug and remaining path while removing the program ID segment. This effectively migrates old /[slug]/programs/prog_[id]/:path* URLs to the new simplified /[slug]/program/:path* structure.


29-32: Consistent update for new routing structure.

The redirect rule correctly updated to match the new singular "program" path structure and removes the program ID dependency from the URL pattern.


34-37: Consistent update for branding redirect.

The redirect rule properly updated to use the new singular "program" path structure while maintaining the same logical redirect behavior.


39-42: Consistent update for sales redirect.

The redirect rule correctly updated to use the new simplified routing structure, removing the program ID dependency while maintaining the sales-to-commissions redirect logic.

@steven-tey steven-tey merged commit 85880d2 into main Jun 7, 2025
8 checks passed
@steven-tey steven-tey deleted the program-route branch June 7, 2025 02:51
@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 9, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2498:

To re-run the tests, please comment @bug0 run or push a new commit to this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants