Skip to content

Commit 0fc01fa

Browse files
authored
Add internal approved_invited status to show both approved and invited statuses (dubinc#3718)
1 parent 44c5f14 commit 0fc01fa

8 files changed

Lines changed: 80 additions & 22 deletions

File tree

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

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import usePartnersCount from "@/lib/swr/use-partners-count";
88
import useProgram from "@/lib/swr/use-program";
99
import useWorkspace from "@/lib/swr/use-workspace";
1010
import { EnrolledPartnerProps } from "@/lib/types";
11+
import { ACTIVE_ENROLLMENT_STATUSES } from "@/lib/zod/schemas/partners";
1112
import { useArchivePartnerModal } from "@/ui/modals/archive-partner-modal";
1213
import { useBanPartnerModal } from "@/ui/modals/ban-partner-modal";
1314
import { useBulkArchivePartnersModal } from "@/ui/modals/bulk-archive-partners-modal";
@@ -27,6 +28,7 @@ import { ProgramEnrollmentStatus } from "@dub/prisma/client";
2728
import {
2829
AnimatedSizeContainer,
2930
Button,
31+
DynamicTooltipWrapper,
3032
EditColumnsButton,
3133
Filter,
3234
Icon,
@@ -122,7 +124,7 @@ export function PartnersTable() {
122124
const status = (
123125
searchParams.get("status") || searchParams.get("search")
124126
? undefined
125-
: "approved"
127+
: "approved_invited"
126128
) as ProgramEnrollmentStatus;
127129

128130
const sortBy =
@@ -529,7 +531,7 @@ export function PartnersTable() {
529531
}}
530532
/>
531533

532-
{(status === "approved" ||
534+
{(!searchParams.get("status") ||
533535
searchParams.get("status") === "approved") && (
534536
<BulkActionsMenu
535537
table={table}
@@ -651,6 +653,12 @@ function BulkActionsMenu({
651653

652654
const partnerWord = selectedPartners.length === 1 ? "partner" : "partners";
653655

656+
const disabledTooltip = selectedPartners.some(
657+
(partner) => !ACTIVE_ENROLLMENT_STATUSES.includes(partner.status),
658+
)
659+
? `You cannot perform this action because one or more partners are not in ${ACTIVE_ENROLLMENT_STATUSES.join(", ")} statuses.`
660+
: undefined;
661+
654662
return (
655663
<Popover
656664
openPopover={isOpen}
@@ -666,6 +674,7 @@ function BulkActionsMenu({
666674
onArchivePartners(selectedPartners);
667675
setIsOpen(false);
668676
}}
677+
disabledTooltip={disabledTooltip}
669678
/>
670679
<MenuItem
671680
icon={CircleXmark}
@@ -674,6 +683,7 @@ function BulkActionsMenu({
674683
onDeactivatePartners(selectedPartners);
675684
setIsOpen(false);
676685
}}
686+
disabledTooltip={disabledTooltip}
677687
/>
678688
<MenuItem
679689
icon={UserDelete}
@@ -683,6 +693,7 @@ function BulkActionsMenu({
683693
onBanPartners(selectedPartners);
684694
setIsOpen(false);
685695
}}
696+
disabledTooltip={disabledTooltip}
686697
/>
687698
</Command.Group>
688699
</Command.List>
@@ -939,11 +950,13 @@ function MenuItem({
939950
label,
940951
onSelect,
941952
variant = "default",
953+
disabledTooltip,
942954
}: {
943955
icon: Icon;
944956
label: string;
945957
onSelect: () => void;
946958
variant?: "default" | "danger";
959+
disabledTooltip?: string | boolean;
947960
}) {
948961
const variantStyles = {
949962
default: {
@@ -959,16 +972,22 @@ function MenuItem({
959972
const { text, icon } = variantStyles[variant];
960973

961974
return (
962-
<Command.Item
963-
className={cn(
964-
"flex cursor-pointer select-none items-center gap-2 whitespace-nowrap rounded-md p-2 text-sm",
965-
"data-[selected=true]:bg-neutral-100",
966-
text,
967-
)}
968-
onSelect={onSelect}
975+
<DynamicTooltipWrapper
976+
tooltipProps={disabledTooltip ? { content: disabledTooltip } : undefined}
969977
>
970-
<IconComp className={cn("size-4 shrink-0", icon)} />
971-
{label}
972-
</Command.Item>
978+
<Command.Item
979+
className={cn(
980+
"flex cursor-pointer select-none items-center gap-2 whitespace-nowrap rounded-md p-2 text-sm",
981+
disabledTooltip
982+
? "cursor-not-allowed opacity-75"
983+
: "data-[selected=true]:bg-neutral-100",
984+
text,
985+
)}
986+
onSelect={disabledTooltip ? undefined : onSelect}
987+
>
988+
<IconComp className={cn("size-4 shrink-0", icon)} />
989+
{label}
990+
</Command.Item>
991+
</DynamicTooltipWrapper>
973992
);
974993
}

apps/web/lib/actions/partners/bulk-archive-partners.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
import { recordAuditLog } from "@/lib/api/audit-logs/record-audit-log";
44
import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw";
5-
import { bulkArchivePartnersSchema } from "@/lib/zod/schemas/partners";
5+
import {
6+
ACTIVE_ENROLLMENT_STATUSES,
7+
bulkArchivePartnersSchema,
8+
} from "@/lib/zod/schemas/partners";
69
import { prisma } from "@dub/prisma";
710
import { waitUntil } from "@vercel/functions";
811
import { authActionClient } from "../safe-action";
@@ -28,7 +31,7 @@ export const bulkArchivePartnersAction = authActionClient
2831
},
2932
programId,
3033
status: {
31-
not: "archived",
34+
in: ACTIVE_ENROLLMENT_STATUSES,
3235
},
3336
},
3437
select: {

apps/web/lib/actions/partners/bulk-ban-partners.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import { recordAuditLog } from "@/lib/api/audit-logs/record-audit-log";
44
import { resolveFraudGroups } from "@/lib/api/fraud/resolve-fraud-groups";
55
import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw";
66
import { enqueueBatchJobs } from "@/lib/cron/enqueue-batch-jobs";
7-
import { bulkBanPartnersSchema } from "@/lib/zod/schemas/partners";
7+
import {
8+
ACTIVE_ENROLLMENT_STATUSES,
9+
bulkBanPartnersSchema,
10+
} from "@/lib/zod/schemas/partners";
811
import { prisma } from "@dub/prisma";
912
import { ProgramEnrollmentStatus } from "@dub/prisma/client";
1013
import { APP_DOMAIN_WITH_NGROK } from "@dub/utils";
@@ -32,7 +35,7 @@ export const bulkBanPartnersAction = authActionClient
3235
},
3336
programId,
3437
status: {
35-
not: "banned",
38+
in: ACTIVE_ENROLLMENT_STATUSES,
3639
},
3740
},
3841
select: {

apps/web/lib/api/partners/get-partners-count.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@ export async function getPartnersCount<T>(
4141
...(groupId && {
4242
groupId,
4343
}),
44-
status,
44+
status:
45+
status === "approved_invited"
46+
? {
47+
in: ["approved", "invited"],
48+
}
49+
: status,
4550
...enrollmentMetricWhere,
4651
},
4752
},
@@ -108,7 +113,12 @@ export async function getPartnersCount<T>(
108113
}),
109114
...commonWhere,
110115
},
111-
status,
116+
status:
117+
status === "approved_invited"
118+
? {
119+
in: ["approved", "invited"],
120+
}
121+
: status,
112122
...enrollmentMetricWhere,
113123
},
114124
_count: true,

apps/web/lib/api/partners/program-enrollment-query.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,12 @@ export function buildProgramEnrollmentWhereForList(
153153
in: partnerIds,
154154
},
155155
}),
156-
status,
156+
status:
157+
status === "approved_invited"
158+
? {
159+
in: ["approved", "invited"],
160+
}
161+
: status,
157162
groupId,
158163
...(country || search || email
159164
? {

apps/web/lib/zod/schemas/partners.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ export const getPartnersQuerySchema = z
191191
.extend(getPaginationQuerySchema({ pageSize: PARTNERS_MAX_PAGE_SIZE }));
192192

193193
export const getPartnersQuerySchemaExtended = getPartnersQuerySchema.extend({
194+
status: z
195+
.enum(ProgramEnrollmentStatus)
196+
.or(z.enum(["approved_invited"]))
197+
.optional(),
194198
partnerIds: z
195199
.union([z.string(), z.array(z.string())])
196200
.transform((v) => (Array.isArray(v) ? v : v.split(",")))

apps/web/ui/customers/customers-table/customers-table.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ export function CustomersTable({
404404
sortBy={sortBy}
405405
sortOrder={sortOrder}
406406
enabled={canManageCustomers}
407+
isProgramPage={isProgramPage}
407408
/>
408409
{!canManageCustomers || customers?.length !== 0 ? (
409410
<Table
@@ -491,10 +492,12 @@ function CustomersFilters({
491492
sortBy,
492493
sortOrder,
493494
enabled,
495+
isProgramPage,
494496
}: {
495497
sortBy: string;
496498
sortOrder: "asc" | "desc";
497499
enabled: boolean;
500+
isProgramPage: boolean;
498501
}) {
499502
const {
500503
filters,
@@ -504,7 +507,7 @@ function CustomersFilters({
504507
onRemoveAll,
505508
setSearch,
506509
setSelectedFilter,
507-
} = useCustomerFilters({ sortBy, sortOrder }, { enabled });
510+
} = useCustomerFilters({ sortBy, sortOrder }, { enabled, isProgramPage });
508511

509512
return (
510513
<div>

apps/web/ui/customers/customers-table/use-customer-filters.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ import { useDebounce } from "use-debounce";
1616

1717
export function useCustomerFilters(
1818
extraSearchParams: Record<string, string>,
19-
{ enabled = true }: { enabled?: boolean } = {},
19+
{
20+
enabled = true,
21+
isProgramPage = false,
22+
}: { enabled?: boolean; isProgramPage?: boolean } = {},
2023
) {
2124
const { searchParamsObj, queryParams } = useRouterStuff();
22-
const { id: workspaceId, slug } = useWorkspace();
25+
const { id: workspaceId, slug, defaultProgramId } = useWorkspace();
2326

2427
const [selectedFilter, setSelectedFilter] = useState<string | null>(null);
2528
const [search, setSearch] = useState("");
@@ -38,6 +41,10 @@ export function useCustomerFilters(
3841
>({
3942
query: {
4043
groupBy: "country",
44+
...(isProgramPage &&
45+
defaultProgramId && {
46+
programId: defaultProgramId,
47+
}),
4148
},
4249
enabled,
4350
});
@@ -53,6 +60,10 @@ export function useCustomerFilters(
5360
>({
5461
query: {
5562
groupBy: "linkId",
63+
...(isProgramPage &&
64+
defaultProgramId && {
65+
programId: defaultProgramId,
66+
}),
5667
},
5768
enabled,
5869
});

0 commit comments

Comments
 (0)