diff --git a/src/checkout/hooks/useCreatePaymentSession.ts b/src/checkout/hooks/useCreatePaymentSession.ts index a3368c1c..66f7c377 100644 --- a/src/checkout/hooks/useCreatePaymentSession.ts +++ b/src/checkout/hooks/useCreatePaymentSession.ts @@ -1,9 +1,11 @@ import { createPaymentSession } from "checkout/lib"; import { useCallback, useState } from "react"; import { useAdvertiser } from "auth/hooks/queries/useAdvertiser"; +import { useHistory } from "react-router-dom"; export function useCreatePaymentSession() { const [loading, setLoading] = useState(false); + const history = useHistory(); const { advertiser } = useAdvertiser(); const replaceSession = useCallback(async (campaignId: string) => { @@ -15,6 +17,7 @@ export function useCreatePaymentSession() { .catch((e) => { alert("Unable to create payment session. Please try again."); setLoading(false); + history.push(`/user/main/adsmanager/advanced/${campaignId}/settings`); }); }, []); diff --git a/src/graphql/campaign.generated.tsx b/src/graphql/campaign.generated.tsx index 69bf2fdc..0cf619a8 100644 --- a/src/graphql/campaign.generated.tsx +++ b/src/graphql/campaign.generated.tsx @@ -28,6 +28,7 @@ export type CampaignFragment = { paymentType: Types.PaymentType; dayProportion?: number | null; stripePaymentId?: string | null; + hasPaymentIntent?: boolean | null; geoTargets?: Array<{ __typename?: "Geocode"; code: string; @@ -196,6 +197,7 @@ export type LoadCampaignQuery = { paymentType: Types.PaymentType; dayProportion?: number | null; stripePaymentId?: string | null; + hasPaymentIntent?: boolean | null; geoTargets?: Array<{ __typename?: "Geocode"; code: string; @@ -369,6 +371,7 @@ export const CampaignFragmentDoc = gql` dayProportion stripePaymentId paymentType + hasPaymentIntent geoTargets { code name diff --git a/src/graphql/campaign.graphql b/src/graphql/campaign.graphql index 7a4bf608..1ca98e5d 100644 --- a/src/graphql/campaign.graphql +++ b/src/graphql/campaign.graphql @@ -22,6 +22,7 @@ fragment Campaign on Campaign { dayProportion stripePaymentId paymentType + hasPaymentIntent geoTargets { code name diff --git a/src/graphql/types.ts b/src/graphql/types.ts index e79df52a..bea17794 100644 --- a/src/graphql/types.ts +++ b/src/graphql/types.ts @@ -337,6 +337,7 @@ export type NotificationPayloadInput = { export enum PaymentType { ManualBat = "MANUAL_BAT", Netsuite = "NETSUITE", + Radom = "RADOM", Stripe = "STRIPE", } diff --git a/src/user/library/index.ts b/src/user/library/index.ts index f95cdde1..b8f146c8 100644 --- a/src/user/library/index.ts +++ b/src/user/library/index.ts @@ -160,6 +160,7 @@ export function editCampaignValues( }; }), advertiserId, + hasPaymentIntent: campaign.hasPaymentIntent ?? false, creatives: creativeList(ads).map((a) => a.id!), newCreative: initialCreative, isCreating: false, @@ -219,6 +220,7 @@ export function transformEditForm( startAt: form.startAt, state: form.state, type: form.type, + paymentType: form.paymentType, adSets: form.adSets.map((adSet) => ({ id: adSet.id, segments: adSet.segments.map((v) => ({ code: v.code, name: v.name })), diff --git a/src/user/views/adsManager/types/index.ts b/src/user/views/adsManager/types/index.ts index 2cc37ba9..c248e8a6 100644 --- a/src/user/views/adsManager/types/index.ts +++ b/src/user/views/adsManager/types/index.ts @@ -32,7 +32,9 @@ export type CampaignForm = { price: number; billingType: Billing; pacingStrategy: CampaignPacingStrategies; + hasPaymentIntent: boolean; stripePaymentId?: string | null; + radomPaymentId?: string | null; paymentType: PaymentType; }; @@ -109,6 +111,7 @@ export const initialCampaign = (advertiser: IAdvertiser): CampaignForm => { validateStart: true, isCreating: false, budget: MIN_PER_CAMPAIGN, + hasPaymentIntent: false, currency: "USD", dailyBudget: MIN_PER_CAMPAIGN, dailyCap: 1, diff --git a/src/user/views/adsManager/views/advanced/components/campaign/BudgetSettings.tsx b/src/user/views/adsManager/views/advanced/components/campaign/BudgetSettings.tsx new file mode 100644 index 00000000..b1036228 --- /dev/null +++ b/src/user/views/adsManager/views/advanced/components/campaign/BudgetSettings.tsx @@ -0,0 +1,13 @@ +import React from "react"; +import { BudgetField } from "user/views/adsManager/views/advanced/components/campaign/fields/BudgetField"; +import { PaymentMethodField } from "user/views/adsManager/views/advanced/components/campaign/fields/PaymentMethodField"; + +export function BudgetSettings(props: { isEdit: boolean }) { + return ( + <> + + + + + ); +} diff --git a/src/user/views/adsManager/views/advanced/components/campaign/fields/BudgetField.tsx b/src/user/views/adsManager/views/advanced/components/campaign/fields/BudgetField.tsx index 4387bf4a..e2818c5c 100644 --- a/src/user/views/adsManager/views/advanced/components/campaign/fields/BudgetField.tsx +++ b/src/user/views/adsManager/views/advanced/components/campaign/fields/BudgetField.tsx @@ -1,4 +1,4 @@ -import { Box, Divider, InputAdornment, Stack, Typography } from "@mui/material"; +import { InputAdornment, Stack, Typography } from "@mui/material"; import { FormikRadioControl, FormikTextField } from "form/FormikHelpers"; import React, { useEffect, useState } from "react"; import { useFormikContext } from "formik"; @@ -6,7 +6,6 @@ import { CampaignForm } from "../../../../../types"; import { differenceInHours } from "date-fns"; import { MIN_PER_CAMPAIGN, MIN_PER_DAY } from "validation/CampaignSchema"; import { useAdvertiser } from "auth/hooks/queries/useAdvertiser"; -import { PaymentType } from "graphql/types"; import _ from "lodash"; import { CardContainer } from "components/Card/CardContainer"; @@ -62,7 +61,11 @@ export function BudgetField({ isEdit }: Props) { : undefined } error={!!errors.budget || !!errors.dailyBudget} - disabled={isEdit && !advertiser.selfServiceSetPrice} + disabled={ + isEdit && + !advertiser.selfServiceSetPrice && + values.state !== "draft" + } /> {!advertiser.selfServiceSetPrice ? ( @@ -85,7 +88,7 @@ export function BudgetField({ isEdit }: Props) { $ ), }} - disabled={isEdit} + disabled={isEdit && values.state !== "draft"} /> )} - - - - Payment Method - - - Prepayment of the campaign budget is required before your campaign - can begin.{" "} - {values.paymentType !== PaymentType.Stripe - ? "We will contact you to arrange payment after you submit your campaign for approval." - : ""} - - - ); diff --git a/src/user/views/adsManager/views/advanced/components/campaign/fields/PaymentMethodField.tsx b/src/user/views/adsManager/views/advanced/components/campaign/fields/PaymentMethodField.tsx new file mode 100644 index 00000000..d3c8252d --- /dev/null +++ b/src/user/views/adsManager/views/advanced/components/campaign/fields/PaymentMethodField.tsx @@ -0,0 +1,40 @@ +import { Stack, Typography } from "@mui/material"; +import { FormikRadioControl } from "form/FormikHelpers"; +import { PaymentType } from "graphql/types"; +import React from "react"; +import { useFormikContext } from "formik"; +import { CampaignForm } from "user/views/adsManager/types"; +import { useAdvertiser } from "auth/hooks/queries/useAdvertiser"; +import { CardContainer } from "components/Card/CardContainer"; + +interface Props { + isEdit: boolean; +} + +export function PaymentMethodField({ isEdit }: Props) { + const { values } = useFormikContext(); + const { advertiser } = useAdvertiser(); + + if (advertiser.selfServiceSetPrice) { + return null; + } + + return ( + + + + Prepayment of the campaign budget is required before your campaign can + begin. + + + + + ); +} diff --git a/src/user/views/adsManager/views/advanced/components/completionForm/CompletionForm.tsx b/src/user/views/adsManager/views/advanced/components/completionForm/CompletionForm.tsx index 145c2e86..549d5cf8 100644 --- a/src/user/views/adsManager/views/advanced/components/completionForm/CompletionForm.tsx +++ b/src/user/views/adsManager/views/advanced/components/completionForm/CompletionForm.tsx @@ -1,8 +1,7 @@ import React, { useState } from "react"; import { useHistory, useParams } from "react-router-dom"; -import { Box, Card, Container, Stack, Typography } from "@mui/material"; -import present from "../../../../../../../../present.png"; +import { Card, Container, Stack, Typography } from "@mui/material"; import { LoadingButton } from "@mui/lab"; import { useValidatePaymentSession } from "checkout/hooks/useValidatePaymentSession"; @@ -25,21 +24,17 @@ export function CompletionForm() { }); return ( - + - - - - - Congratulations! + Congratulations! 🎉 {params.mode === "edit" && ( diff --git a/src/user/views/adsManager/views/advanced/components/form/EditCampaign.tsx b/src/user/views/adsManager/views/advanced/components/form/EditCampaign.tsx index 217cad1f..017e84db 100644 --- a/src/user/views/adsManager/views/advanced/components/form/EditCampaign.tsx +++ b/src/user/views/adsManager/views/advanced/components/form/EditCampaign.tsx @@ -12,7 +12,6 @@ import { useHistory, useParams } from "react-router-dom"; import { BaseForm } from "./components/BaseForm"; import { useAdvertiser } from "auth/hooks/queries/useAdvertiser"; import { useCreatePaymentSession } from "checkout/hooks/useCreatePaymentSession"; -import { PaymentType } from "graphql/types"; import { ErrorDetail } from "components/Error/ErrorDetail"; interface Params { @@ -36,11 +35,7 @@ export function EditCampaign() { const [mutation] = useUpdateCampaignMutation({ onCompleted(data) { - const campaign = initialData?.campaign; - if ( - campaign?.stripePaymentId || - campaign?.paymentType !== PaymentType.Stripe - ) { + if (initialData?.campaign?.hasPaymentIntent) { history.push( `/user/main/complete/edit?referenceId=${data.updateCampaign.id}`, ); @@ -67,7 +62,6 @@ export function EditCampaign() { } const initialValues = editCampaignValues(initialData.campaign, advertiser.id); - return ( , + component: , }, { label: "Ads", diff --git a/src/user/views/adsManager/views/advanced/components/form/components/PaymentButton.tsx b/src/user/views/adsManager/views/advanced/components/form/components/PaymentButton.tsx index 9df9272b..ae64a0fc 100644 --- a/src/user/views/adsManager/views/advanced/components/form/components/PaymentButton.tsx +++ b/src/user/views/adsManager/views/advanced/components/form/components/PaymentButton.tsx @@ -6,15 +6,13 @@ import { PaymentType } from "graphql/types"; export function PaymentButton(props: { isEdit: boolean }) { const { values } = useFormikContext(); - const hasPaymentIntent = - values.paymentType !== PaymentType.Stripe || values.stripePaymentId; const paymentText = "Make payment & submit for approval"; return (