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

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export async function sendStripePayouts({
id: true,
email: true,
stripeConnectId: true,
minWithdrawalAmount: true,
},
},
program: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,20 @@
"use client";

import { updatePartnerPayoutSettingsAction } from "@/lib/actions/partners/update-partner-payout-settings";
import {
ALLOWED_MIN_WITHDRAWAL_AMOUNTS,
BELOW_MIN_WITHDRAWAL_FEE_CENTS,
MIN_WITHDRAWAL_AMOUNT_CENTS,
} from "@/lib/partners/constants";
import { mutatePrefix } from "@/lib/swr/mutate";
import usePartnerProfile from "@/lib/swr/use-partner-profile";
import { partnerPayoutSettingsSchema } from "@/lib/zod/schemas/partners";
import { ConnectPayoutButton } from "@/ui/partners/connect-payout-button";
import { PayoutMethodsDropdown } from "@/ui/partners/payout-methods-dropdown";
import {
AnimatedSizeContainer,
Button,
InfoTooltip,
Sheet,
SimpleTooltipContent,
Slider,
useScrollProgress,
} from "@dub/ui";
import {
CONNECT_SUPPORTED_COUNTRIES,
COUNTRIES,
currencyFormatter,
} from "@dub/utils";
import { CONNECT_SUPPORTED_COUNTRIES, COUNTRIES } from "@dub/utils";
import { COUNTRY_CURRENCY_CODES } from "@dub/utils/src";
import NumberFlow from "@number-flow/react";
import { PartyPopper } from "lucide-react";
import { useAction } from "next-safe-action/hooks";
import Link from "next/link";
import {
Expand Down Expand Up @@ -82,7 +69,6 @@ function PartnerPayoutSettingsSheetInner({
companyName: partner?.companyName || undefined,
address: partner?.invoiceSettings?.address || undefined,
taxId: partner?.invoiceSettings?.taxId || undefined,
minWithdrawalAmount: partner?.minWithdrawalAmount,
},
});

Expand All @@ -104,8 +90,6 @@ function PartnerPayoutSettingsSheetInner({
await executeAsync(data);
};

const minWithdrawalAmount = watch("minWithdrawalAmount");

const scrollRef = useRef<HTMLDivElement>(null);
const { scrollProgress, updateScrollProgress } = useScrollProgress(scrollRef);

Expand Down Expand Up @@ -175,71 +159,6 @@ function PartnerPayoutSettingsSheetInner({
)}
</div>

{/* Minimum withdrawal amount */}
{partner?.country &&
CONNECT_SUPPORTED_COUNTRIES.includes(partner.country) && (
<div className="space-y-6 py-6">
<div>
<h4 className="text-base font-semibold leading-6 text-neutral-900">
Minimum withdrawal amount
</h4>
<p className="text-sm font-medium text-neutral-500">
Set the minimum amount for funds to be automatically
withdrawn from Dub into your connected payout account.
</p>
</div>

<div>
<NumberFlow
value={minWithdrawalAmount / 100}
suffix=" USD"
format={{
style: "currency",
currency: "USD",
// @ts-ignore – trailingZeroDisplay is a valid option but TS is outdated
trailingZeroDisplay: "stripIfInteger",
}}
className="mb-2 text-2xl font-medium leading-6 text-neutral-800"
/>

<Slider
value={minWithdrawalAmount}
min={ALLOWED_MIN_WITHDRAWAL_AMOUNTS[0]}
max={
ALLOWED_MIN_WITHDRAWAL_AMOUNTS[
ALLOWED_MIN_WITHDRAWAL_AMOUNTS.length - 1
]
}
onChange={(value) => {
const closest = ALLOWED_MIN_WITHDRAWAL_AMOUNTS.reduce(
(prev, curr) =>
Math.abs(curr - value) < Math.abs(prev - value)
? curr
: prev,
);

setValue("minWithdrawalAmount", closest, {
shouldDirty: true,
});
}}
marks={ALLOWED_MIN_WITHDRAWAL_AMOUNTS}
hint={
<AnimatedSizeContainer height>
{minWithdrawalAmount < MIN_WITHDRAWAL_AMOUNT_CENTS ? (
`${currencyFormatter(BELOW_MIN_WITHDRAWAL_FEE_CENTS / 100)} withdrawal fee for balances under ${currencyFormatter(MIN_WITHDRAWAL_AMOUNT_CENTS / 100)}. If you have any previously processed payouts, they will be automatically transferred to your connected bank account once the minimum withdrawal amount is reached.`
) : (
<div className="flex items-center gap-1 text-xs font-normal leading-4 text-neutral-500">
<PartyPopper className="size-4" />
Free withdrawals unlocked
</div>
)}
</AnimatedSizeContainer>
}
/>
</div>
</div>
)}

{/* Invoice details */}
<div className="space-y-6 py-6">
<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { ConditionalLink } from "@/ui/shared/conditional-link";
import { X } from "@/ui/shared/icons";
import {
Button,
buttonVariants,
InvoiceDollar,
LoadingSpinner,
Sheet,
Expand Down Expand Up @@ -177,57 +176,61 @@ function PayoutDetailsSheetContent({ payout }: PayoutDetailsSheetProps) {
} as any);

return (
<div>
<div className="flex h-16 items-center justify-between border-b border-neutral-200 px-6 py-4">
<Sheet.Title className="text-lg font-semibold">
Payout details
</Sheet.Title>
<Sheet.Close asChild>
<Button
variant="outline"
icon={<X className="size-5" />}
className="h-auto w-fit p-1"
/>
</Sheet.Close>
</div>
<div className="flex flex-col gap-4 p-6">
<div className="text-base font-medium text-neutral-900">
Invoice details
</div>
<div className="grid grid-cols-2 gap-3 text-sm">
{Object.entries(invoiceData).map(([key, value]) => (
<Fragment key={key}>
<div className="flex items-center font-medium text-neutral-500">
{key}
</div>
<div className="text-neutral-800">{value}</div>
</Fragment>
))}
<div className="flex h-full flex-col">
<div className="sticky top-0 z-10 border-b border-neutral-200 bg-white">
<div className="flex h-16 items-center justify-between px-6 py-4">
<Sheet.Title className="text-lg font-semibold">
Payout details
</Sheet.Title>
<Sheet.Close asChild>
<Button
variant="outline"
icon={<X className="size-5" />}
className="h-auto w-fit p-1"
/>
</Sheet.Close>
</div>
</div>
{isLoading ? (
<div className="flex h-full items-center justify-center">
<LoadingSpinner />

<div className="flex grow flex-col">
<div className="flex flex-col gap-4 p-6">
<div className="text-base font-medium text-neutral-900">
Invoice details
</div>
<div className="grid grid-cols-2 gap-3 text-sm">
{Object.entries(invoiceData).map(([key, value]) => (
<Fragment key={key}>
<div className="flex items-center font-medium text-neutral-500">
{key}
</div>
<div className="text-neutral-800">{value}</div>
</Fragment>
))}
</div>
</div>
) : earnings?.length ? (
<>

{isLoading ? (
<div className="flex h-full items-center justify-center">
<LoadingSpinner />
</div>
) : earnings?.length ? (
<div className="p-6 pt-2">
<Table {...table} />
</div>
<div className="sticky bottom-0 z-10 flex justify-end border-t border-neutral-200 bg-white px-6 py-4">
<Link
href={`/programs/${payout.program.slug}/earnings?payoutId=${payout.id}&start=${payout.periodStart}&end=${payout.periodEnd}`}
target="_blank"
className={cn(
buttonVariants({ variant: "secondary" }),
"flex h-7 items-center rounded-lg border px-2 text-sm",
)}
>
View all
</Link>
</div>
</>
) : null}
) : null}
</div>

<div className="sticky bottom-0 z-10 border-t border-neutral-200 bg-white">
<div className="flex items-center justify-between gap-2 p-5">
<Link
href={`/programs/${payout.program.slug}/earnings?payoutId=${payout.id}&start=${payout.periodStart}&end=${payout.periodEnd}`}
target="_blank"
className="w-full"
>
<Button variant="secondary" text="View all" />
</Link>
</div>
</div>
</div>
);
}
Expand Down
Loading