Skip to content

Commit 040b7c1

Browse files
authored
Merge branch 'main' into program-marketplace-categories
2 parents 54f4d70 + 94fb773 commit 040b7c1

27 files changed

Lines changed: 364 additions & 117 deletions

File tree

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

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { getPartners } from "@/lib/api/partners/get-partners";
33
import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw";
44
import { getProgramOrThrow } from "@/lib/api/programs/get-program-or-throw";
55
import { parseRequestBody } from "@/lib/api/utils";
6+
import { applicationEventSchema } from "@/lib/application-events/schema";
67
import { withWorkspace } from "@/lib/auth";
78
import { throwIfPartnersLimitExceeded } from "@/lib/partners/throw-if-partners-limit-exceeded";
89
import { polyfillSocialMediaFields } from "@/lib/social-utils";
@@ -50,25 +51,22 @@ export const GET = withWorkspace(
5051
country: filterOverrides.country,
5152
}),
5253
};
53-
const {
54-
sortBy: sortByWithOldFields,
55-
includePartnerPlatforms,
56-
...parsedParams
57-
} = getPartnersQuerySchemaExtended
58-
.extend({
59-
// add old fields for backward compatibility
60-
sortBy: getPartnersQuerySchemaExtended.shape.sortBy.or(
61-
z.enum([
62-
"clicks",
63-
"leads",
64-
"conversions",
65-
"sales",
66-
"saleAmount",
67-
"totalSales",
68-
]),
69-
),
70-
})
71-
.parse(paramsToParse);
54+
const { sortBy: sortByWithOldFields, ...parsedParams } =
55+
getPartnersQuerySchemaExtended
56+
.extend({
57+
// add old fields for backward compatibility
58+
sortBy: getPartnersQuerySchemaExtended.shape.sortBy.or(
59+
z.enum([
60+
"clicks",
61+
"leads",
62+
"conversions",
63+
"sales",
64+
"saleAmount",
65+
"totalSales",
66+
]),
67+
),
68+
})
69+
.parse(paramsToParse);
7270

7371
// get the final sortBy field (replace old fields with new fields)
7472
const sortBy =
@@ -104,11 +102,16 @@ export const GET = withWorkspace(
104102
saleAmount: z.number().default(0),
105103
});
106104

107-
const responseSchema = includePartnerPlatforms
108-
? baseSchema.extend({
109-
platforms: z.array(partnerPlatformSchema),
110-
})
111-
: baseSchema;
105+
const responseSchema =
106+
parsedParams.includeApplicationEvent ||
107+
parsedParams.includePartnerPlatforms
108+
? baseSchema.extend({
109+
platforms: z.array(partnerPlatformSchema),
110+
applicationEvent: applicationEventSchema
111+
.pick({ referralSource: true })
112+
.nullish(),
113+
})
114+
: baseSchema;
112115

113116
return NextResponse.json(
114117
z.array(responseSchema).parse(

apps/web/app/(ee)/api/stripe/integration/webhook/checkout-session-completed.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,11 +535,13 @@ export async function checkoutSessionCompleted(
535535
workspaceId: workspace.id,
536536
programId: link.programId,
537537
partnerId: link.partnerId,
538+
customerId: customer.id,
539+
customerFirstSaleAt: customer.firstSaleAt ?? new Date(),
538540
},
539541
metrics: {
540542
current: {
541-
saleAmount: saleData.amount,
542543
conversions: firstConversionFlag ? 1 : 0,
544+
saleAmount: saleData.amount,
543545
},
544546
},
545547
}),

apps/web/app/(ee)/api/stripe/integration/webhook/invoice-paid.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,13 @@ export async function invoicePaid(
369369
workspaceId: workspace.id,
370370
programId: link.programId,
371371
partnerId: link.partnerId,
372+
customerId: customer.id,
373+
customerFirstSaleAt: customer.firstSaleAt ?? new Date(),
372374
},
373375
metrics: {
374376
current: {
375-
saleAmount: saleData.amount,
376377
conversions: firstConversionFlag ? 1 : 0,
378+
saleAmount: saleData.amount,
377379
},
378380
},
379381
}),

apps/web/app/api/links/export/route.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import { getLinksForWorkspace } from "@/lib/api/links/get-links-for-workspace";
66
import { throwIfClicksUsageExceeded } from "@/lib/api/links/usage-checks";
77
import { validateLinksQueryFilters } from "@/lib/api/links/validate-links-query-filters";
88
import { withWorkspace } from "@/lib/auth";
9-
import { MEGA_WORKSPACE_LINKS_LIMIT } from "@/lib/constants/misc";
9+
import {
10+
MEGA_WORKSPACE_LINKS_LIMIT,
11+
SORTABLE_LINKS_LIMIT,
12+
} from "@/lib/constants/misc";
1013
import { qstash } from "@/lib/cron";
1114
import { linksExportQuerySchema } from "@/lib/zod/schemas/links";
1215
import { APP_DOMAIN_WITH_NGROK } from "@dub/utils";
@@ -62,6 +65,10 @@ export const GET = withWorkspace(
6265
startDate,
6366
endDate,
6467
}),
68+
sortBy:
69+
workspace.totalLinks > SORTABLE_LINKS_LIMIT
70+
? "createdAt"
71+
: filters.sortBy,
6572
searchMode:
6673
workspace.totalLinks > MEGA_WORKSPACE_LINKS_LIMIT ? "exact" : "fuzzy",
6774
includeDashboard: false,

apps/web/app/api/links/route.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import { throwIfLinksUsageExceeded } from "@/lib/api/links/usage-checks";
44
import { validateLinksQueryFilters } from "@/lib/api/links/validate-links-query-filters";
55
import { parseRequestBody } from "@/lib/api/utils";
66
import { withWorkspace } from "@/lib/auth";
7-
import { MEGA_WORKSPACE_LINKS_LIMIT } from "@/lib/constants/misc";
7+
import {
8+
MEGA_WORKSPACE_LINKS_LIMIT,
9+
SORTABLE_LINKS_LIMIT,
10+
} from "@/lib/constants/misc";
811
import { ratelimit } from "@/lib/upstash";
912
import { sendWorkspaceWebhook } from "@/lib/webhook/publish";
1013
import {
@@ -31,6 +34,10 @@ export const GET = withWorkspace(
3134
...filters,
3235
workspaceId: workspace.id,
3336
folderIds,
37+
sortBy:
38+
workspace.totalLinks > SORTABLE_LINKS_LIMIT
39+
? "createdAt"
40+
: filters.sortBy,
3441
searchMode:
3542
workspace.totalLinks > MEGA_WORKSPACE_LINKS_LIMIT ? "exact" : "fuzzy",
3643
});

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/add-edit-bounty/bounty-logic.tsx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ import { Controller } from "react-hook-form";
1313
import { BountyAmountInput } from "./bounty-amount-input";
1414
import { useBountyFormContext } from "./bounty-form-context";
1515

16+
const PERFORMANCE_SCOPE_DESCRIPTIONS = {
17+
new: "Only net-new stats after the bounty start date will be counted",
18+
lifetime: "Include the partner's historical stats in your program",
19+
} as const;
20+
1621
export function BountyLogic({ className }: { className?: string }) {
1722
const { control, watch } = useBountyFormContext();
1823

@@ -33,13 +38,25 @@ export function BountyLogic({ className }: { className?: string }) {
3338
control={control}
3439
name="performanceScope"
3540
render={({ field }) => (
36-
<InlineBadgePopover text={field.value} invalid={!field.value}>
41+
<InlineBadgePopover
42+
text={field.value}
43+
invalid={!field.value}
44+
align="center"
45+
>
3746
<InlineBadgePopoverMenu
3847
selectedValue={field.value}
3948
onSelect={field.onChange}
4049
items={[
41-
{ text: "new", value: "new" },
42-
{ text: "lifetime", value: "lifetime" },
50+
{
51+
text: "new",
52+
value: "new",
53+
description: PERFORMANCE_SCOPE_DESCRIPTIONS.new,
54+
},
55+
{
56+
text: "lifetime",
57+
value: "lifetime",
58+
description: PERFORMANCE_SCOPE_DESCRIPTIONS.lifetime,
59+
},
4360
]}
4461
/>
4562
</InlineBadgePopover>
@@ -58,6 +75,7 @@ export function BountyLogic({ className }: { className?: string }) {
5875
: "activity"
5976
}
6077
invalid={!field.value}
78+
align="center"
6179
>
6280
<InlineBadgePopoverMenu
6381
selectedValue={field.value}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export function useCommissionFilters() {
7979
customers?.map((customer) => {
8080
return {
8181
value: customer.id,
82-
label: customer.email ?? customer.name,
82+
label: customer.email ?? customer.name ?? customer.id,
8383
icon: <CustomerAvatar customer={customer} className="size-4" />,
8484
};
8585
}) ?? null,

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ const applicationsColumns = {
4747
all: [
4848
"partner",
4949
"createdAt",
50+
"source",
51+
"group",
5052
"location",
5153
"website",
5254
"youtube",
@@ -58,6 +60,7 @@ const applicationsColumns = {
5860
defaultVisible: [
5961
"partner",
6062
"createdAt",
63+
"source",
6164
"location",
6265
"website",
6366
"youtube",
@@ -88,6 +91,7 @@ export function ProgramPartnersApplicationsPageClient() {
8891
status: "pending",
8992
});
9093

94+
// TODO: refactor to use `/partners/applications` endpoint
9195
const {
9296
data: partners,
9397
error,
@@ -99,6 +103,7 @@ export function ProgramPartnersApplicationsPageClient() {
99103
status: "pending",
100104
sortBy,
101105
sortOrder,
106+
includeApplicationEvent: true,
102107
includePartnerPlatforms: true,
103108
},
104109
{ exclude: ["partnerId"] },
@@ -163,7 +168,7 @@ export function ProgramPartnersApplicationsPageClient() {
163168
});
164169

165170
const { columnVisibility, setColumnVisibility } = useColumnVisibility(
166-
"applications-table-columns",
171+
"applications-table-columns-v2",
167172
applicationsColumns,
168173
);
169174

@@ -191,10 +196,20 @@ export function ProgramPartnersApplicationsPageClient() {
191196
header: "Applied",
192197
accessorFn: (d) => formatDate(d.createdAt, { month: "short" }),
193198
},
199+
// TODO: add source column back once we fix application source display
200+
// {
201+
// id: "source",
202+
// header: "Source",
203+
// minSize: 170,
204+
// cell: ({ row }) => (
205+
// <PartnerApplicationSource
206+
// referralSource={row.original.applicationEvent?.referralSource}
207+
// />
208+
// ),
209+
// },
194210
{
195211
id: "group",
196212
header: "Group",
197-
enableHiding: false,
198213
minSize: 150,
199214
cell: ({ row }) => {
200215
if (!groups || !row.original.groupId) {

apps/web/lib/api/conversions/track-sale.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,11 +506,13 @@ const _trackSale = async ({
506506
workspaceId: workspace.id,
507507
programId: link.programId,
508508
partnerId: link.partnerId,
509+
customerId: customer.id,
510+
customerFirstSaleAt: customer.firstSaleAt ?? new Date(),
509511
},
510512
metrics: {
511513
current: {
512-
saleAmount: saleData.amount,
513514
conversions: firstConversionFlag ? 1 : 0,
515+
saleAmount: saleData.amount,
514516
},
515517
},
516518
}),

apps/web/lib/api/links/get-links-for-workspace.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export async function getLinksForWorkspace(filters: GetLinksForWorkspaceProps) {
2424
tagNames,
2525
search,
2626
searchMode,
27-
sort,
2827
userId,
2928
showArchived,
3029
withTags,
@@ -40,12 +39,10 @@ export async function getLinksForWorkspace(filters: GetLinksForWorkspaceProps) {
4039
endDate,
4140
} = filters;
4241

43-
// Support legacy sort param
44-
if (sort && sort !== "createdAt") {
45-
filters = { ...filters, sortBy: sort };
46-
}
47-
48-
const paginationQuery = buildPaginationQuery(filters);
42+
const paginationQuery = buildPaginationQuery({
43+
...filters,
44+
sortOrder: "desc",
45+
});
4946

5047
// Validate the provided cursor ID
5148
const cursorId = filters.startingAfter || filters.endingBefore;

0 commit comments

Comments
 (0)