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
109 changes: 78 additions & 31 deletions apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/page-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
Button,
buttonVariants,
DotsPattern,
DynamicTooltipWrapper,
FileUpload,
LoadingSpinner,
ToggleGroup,
Expand Down Expand Up @@ -89,6 +90,7 @@ function FormWrapper({

type ProfileFormData = {
name: string;
email: string;
image: string | null;
description: string | null;
country: string;
Expand All @@ -103,6 +105,7 @@ function FormProvider({
const form = useForm<ProfileFormData>({
defaultValues: {
name: partner.name,
email: partner.email ?? "",
image: partner.image,
description: partner.description ?? null,
country: partner.country ?? "",
Expand All @@ -115,6 +118,8 @@ function FormProvider({
}

function Controls({ formRef }: { formRef: RefObject<HTMLFormElement> }) {
const { partner } = usePartnerProfile();

const { MergePartnerAccountsModal, setShowMergePartnerAccountsModal } =
useMergePartnerAccountsModal();

Expand All @@ -135,7 +140,19 @@ function Controls({ formRef }: { formRef: RefObject<HTMLFormElement> }) {
text="Save changes"
className="h-8 w-fit px-2.5"
loading={isSubmitting}
onClick={() => formRef.current?.requestSubmit()}
onClick={() => {
if (partner?.stripeConnectId) {
const confirmed = window.confirm(
"Updating your email, country, or profile type will reset your Stripe account, which will require you to restart the payouts connection process. Are you sure you want to continue?",
);

if (!confirmed) {
return;
}
}

formRef.current?.requestSubmit();
}}
/>
</>
);
Expand Down Expand Up @@ -252,29 +269,57 @@ function ProfileForm({
/>
</div>
</label>
<label className="flex flex-col gap-1.5">
<span className="text-sm font-medium text-neutral-800">Email</span>
<DynamicTooltipWrapper
tooltipProps={
completedPayoutsCount > 0
? {
content:
"Since you've already received payouts on Dub, you cannot change your email. If you need to update your email, please contact support.",
}
: undefined
}
>
<input
type="email"
className={cn(
"block w-full rounded-md focus:outline-none sm:text-sm",
errors.email
? "border-red-300 pr-10 text-red-900 placeholder-red-300 focus:border-red-500 focus:ring-red-500"
: "border-neutral-300 text-neutral-900 placeholder-neutral-400 focus:border-neutral-500 focus:ring-neutral-500",
completedPayoutsCount > 0 &&
"cursor-not-allowed bg-neutral-100 text-neutral-400",
)}
placeholder="[email protected]"
disabled={completedPayoutsCount > 0}
{...register("email", {
required: true,
})}
/>
</DynamicTooltipWrapper>
</label>
<label className="flex flex-col">
<span className="text-sm font-medium text-neutral-800">
Country
</span>
<div>
<Controller
control={control}
name="country"
rules={{ required: true }}
render={({ field }) => (
<CountryCombobox
value={field.value || ""}
onChange={field.onChange}
error={errors.country ? true : false}
disabledTooltip={
completedPayoutsCount > 0
? "Since you've already received payouts on Dub, you cannot change your country. If you need to update your country, please contact support."
: undefined
}
/>
)}
/>
</div>
<Controller
control={control}
name="country"
rules={{ required: true }}
render={({ field }) => (
<CountryCombobox
value={field.value || ""}
onChange={field.onChange}
error={errors.country ? true : false}
disabledTooltip={
completedPayoutsCount > 0
? "Since you've already received payouts on Dub, you cannot change your country. If you need to update your country, please contact support."
: undefined
}
/>
)}
/>
</label>

<label className="flex flex-col gap-1.5">
Expand Down Expand Up @@ -302,7 +347,16 @@ function ProfileForm({
<span className="text-sm font-medium text-neutral-800">
Profile type
</span>
<div className="w-full">
<DynamicTooltipWrapper
tooltipProps={
completedPayoutsCount > 0
? {
content:
"Since you've already received payouts on Dub, you cannot change your profile type. If you need to update your profile type, please contact support.",
}
: undefined
}
>
<LayoutGroup>
<div className="w-full">
<ToggleGroup
Expand All @@ -328,13 +382,14 @@ function ProfileForm({
)}
optionClassName={cn(
"h-9 flex items-center justify-center rounded-lg flex-1",
completedPayoutsCount > 0 && "pointer-events-none",
completedPayoutsCount > 0 &&
"pointer-events-none text-neutral-400",
)}
indicatorClassName="bg-white"
/>
</div>
</LayoutGroup>
</div>
</DynamicTooltipWrapper>
</label>

<AnimatePresence mode="popLayout">
Expand Down Expand Up @@ -378,14 +433,6 @@ function ProfileForm({
</AnimatePresence>
</div>
</div>
{/* <div className="flex justify-end rounded-b-lg border-t border-neutral-200 bg-neutral-100 px-5 py-3.5">
<Button
type="submit"
text="Save changes"
className="h-8 w-fit px-2.5"
loading={isSubmitting || isPending}
/>
</div> */}
</form>
);
}
56 changes: 36 additions & 20 deletions apps/web/lib/actions/partners/update-partner-profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { authPartnerActionClient } from "../safe-action";
const updatePartnerProfileSchema = z
.object({
name: z.string(),
email: z.string().email(),
image: uploadedImageSchema.nullish(),
description: z.string().nullable(),
country: z.enum(Object.keys(COUNTRIES) as [string, ...string[]]).nullable(),
Expand Down Expand Up @@ -48,8 +49,17 @@ export const updatePartnerProfileAction = authPartnerActionClient
.schema(updatePartnerProfileSchema)
.action(async ({ ctx, parsedInput }) => {
const { partner } = ctx;
const { name, image, description, country, profileType, companyName } =
parsedInput;
const {
name,
email,
image,
description,
country,
profileType,
companyName,
} = parsedInput;

const emailChanged = partner.email !== email;

const countryChanged =
partner.country?.toLowerCase() !== country?.toLowerCase();
Expand All @@ -60,9 +70,16 @@ export const updatePartnerProfileAction = authPartnerActionClient
const companyNameChanged =
partner.companyName?.toLowerCase() !== companyName?.toLowerCase();

if (countryChanged || profileTypeChanged || companyNameChanged) {
// Partner is only able to update their country, profile type, or company name
// as long as they don't have any completed payouts
if (
(emailChanged ||
countryChanged ||
profileTypeChanged ||
companyNameChanged) &&
partner.stripeConnectId &&
partner.payoutsEnabledAt
) {
// Partner is not able to update their country, profile type, or company name
// if they have a verified Stripe Express account + any completed payouts
const completedPayoutsCount = await prisma.payout.count({
where: {
partnerId: partner.id,
Expand All @@ -72,24 +89,22 @@ export const updatePartnerProfileAction = authPartnerActionClient

if (completedPayoutsCount > 0) {
throw new Error(
"Since you've already received payouts on Dub, you cannot change your country or profile type. Please contact support to update those fields.",
"Since you've already received payouts on Dub, you cannot change your email, country or profile type. Please contact support to update those fields.",
);
}

if (partner.stripeConnectId) {
const response = await stripe.accounts.del(partner.stripeConnectId);

if (response.deleted) {
await prisma.partner.update({
where: {
id: partner.id,
},
data: {
stripeConnectId: null,
payoutsEnabledAt: null,
},
});
}
const response = await stripe.accounts.del(partner.stripeConnectId);

if (response.deleted) {
await prisma.partner.update({
where: {
id: partner.id,
},
data: {
stripeConnectId: null,
payoutsEnabledAt: null,
},
});
}
}

Expand All @@ -108,6 +123,7 @@ export const updatePartnerProfileAction = authPartnerActionClient
},
data: {
name,
email,
description,
...(imageUrl && { image: imageUrl }),
country,
Expand Down