Преглед изворни кода

Frontend cleanup, check for payment method

Mauricio Araujo пре 2 година
родитељ
комит
811903fe15

+ 33 - 0
dashboard/src/lib/hooks/useStripe.tsx

@@ -22,6 +22,11 @@ type TCreatePaymentMethod = {
   createPaymentMethod: () => Promise<string>;
 };
 
+type TCheckHasPaymentEnabled = {
+  hasPaymentEnabled: boolean;
+  refetchPaymentEnabled: any;
+};
+
 export const usePaymentMethods = (): TUsePaymentMethod => {
   const { user, currentProject } = useContext(Context);
 
@@ -111,3 +116,31 @@ export const useCreatePaymentMethod = (): TCreatePaymentMethod => {
     createPaymentMethod,
   };
 };
+
+export const checkIfProjectHasPayment = (): TCheckHasPaymentEnabled => {
+  const { currentProject } = useContext(Context);
+
+  if (!currentProject?.id) {
+    throw new Error("Project ID is missing");
+  }
+
+  // Fetch list of payment methods
+  const paymentEnabledReq = useQuery(
+    ["checkPaymentEnabled", currentProject?.id],
+    async () => {
+      const res = await api.getHasBilling(
+        "<token>",
+        {},
+        { project_id: currentProject.id }
+      );
+
+      const data = z.boolean().parse(res.data);
+      return data;
+    }
+  );
+
+  return {
+    hasPaymentEnabled: paymentEnabledReq.data ?? false,
+    refetchPaymentEnabled: paymentEnabledReq.refetch,
+  };
+};

+ 1 - 54
dashboard/src/main/home/Home.tsx

@@ -1,4 +1,5 @@
 import React, { useContext, useEffect, useRef, useState } from "react";
+import { useStripe } from "@stripe/react-stripe-js";
 import { createPortal } from "react-dom";
 import {
   Route,
@@ -108,7 +109,6 @@ const Home: React.FC<Props> = (props) => {
     setHasFinishedOnboarding,
     setCurrentError,
     setCurrentModal,
-    setHasBillingEnabled,
     setUsage,
     setShouldRefreshClusters,
   } = useContext(Context);
@@ -262,46 +262,9 @@ const Home: React.FC<Props> = (props) => {
     }
   }, [shouldRefreshClusters]);
 
-  const checkIfProjectHasBilling = async (projectId: number) => {
-    if (!projectId) {
-      return false;
-    }
-    try {
-      const res = await api.getHasBilling(
-        "<token>",
-        {},
-        { project_id: projectId }
-      );
-      setHasBillingEnabled(res.data?.has_billing);
-      return res?.data?.has_billing;
-    } catch (error) {
-      console.log(error);
-    }
-  };
-
   useEffect(() => {
     getMetadata();
     checkOnboarding();
-    if (!process.env.DISABLE_BILLING) {
-      checkIfProjectHasBilling(currentProject?.id)
-        .then((isBillingEnabled) => {
-          if (isBillingEnabled) {
-            api
-              .getUsage("<token>", {}, { project_id: currentProject?.id })
-              .then((res) => {
-                const usage = res.data;
-                setUsage(usage);
-                /*
-                if (usage.exceeded) {
-                  setCurrentModal("UsageWarningModal", { usage });
-                }
-                */
-              })
-              .catch(console.log);
-          }
-        })
-        .catch(console.log);
-    }
   }, [props.currentProject?.id]);
 
   useEffect(() => {
@@ -411,22 +374,6 @@ const Home: React.FC<Props> = (props) => {
       theme={currentProject?.simplified_view_enabled ? midnight : standard}
     >
       <DeploymentTargetProvider>
-        {currentProject?.sandbox_enabled && (
-          <GlobalBanner>
-            <img src={warning} />
-            Your project is currently in Sandbox mode. Your project will be
-            deleted after one week.
-            <CTA>
-              <ShowIntercomButton
-                alt
-                message="I would like to eject to my own cloud account"
-                height="25px"
-              >
-                Request ejection
-              </ShowIntercomButton>
-            </CTA>
-          </GlobalBanner>
-        )}
         <StyledHome isHosted={currentProject?.sandbox_enabled ?? false}>
           <ModalHandler setRefreshClusters={setForceRefreshClusters} />
           {currentOverlay &&

+ 35 - 6
dashboard/src/main/home/app-dashboard/apps/Apps.tsx

@@ -11,14 +11,17 @@ import Button from "components/porter/Button";
 import Container from "components/porter/Container";
 import DashboardPlaceholder from "components/porter/DashboardPlaceholder";
 import PorterLink from "components/porter/Link";
+import Modal from "components/porter/Modal";
 import SearchBar from "components/porter/SearchBar";
 import Spacer from "components/porter/Spacer";
 import Text from "components/porter/Text";
 import Toggle from "components/porter/Toggle";
 import DashboardHeader from "main/home/cluster-dashboard/DashboardHeader";
 import DeleteEnvModal from "main/home/cluster-dashboard/preview-environments/v2/DeleteEnvModal";
+import BillingModal from "main/home/modals/BillingModal";
 import { clientAddonFromProto, type ClientAddon } from "lib/addons";
 import { useAppAnalytics } from "lib/hooks/useAppAnalytics";
+import { checkIfProjectHasPayment } from "lib/hooks/useStripe";
 
 import api from "shared/api";
 import { Context } from "shared/Context";
@@ -43,6 +46,7 @@ const Apps: React.FC = () => {
   const { currentProject, currentCluster } = useContext(Context);
   const { updateAppStep } = useAppAnalytics();
   const { currentDeploymentTarget } = useDeploymentTarget();
+  const { hasPaymentEnabled } = checkIfProjectHasPayment();
   const history = useHistory();
 
   const [searchValue, setSearchValue] = useState("");
@@ -50,6 +54,7 @@ const Apps: React.FC = () => {
   const [sort, setSort] = useState<"calendar" | "letter">("calendar");
   const [showDeleteEnvModal, setShowDeleteEnvModal] = useState(false);
   const [envDeleting, setEnvDeleting] = useState(false);
+  const [showBillingModal, setShowBillingModal] = useState(false);
 
   const [{ data: apps = [], status }, { data: addons = [] }] = useQueries({
     queries: [
@@ -212,20 +217,45 @@ const Apps: React.FC = () => {
           <Spacer y={0.5} />
           <Text color={"helper"}>Get started by creating an application.</Text>
           <Spacer y={1} />
-          <PorterLink to="/apps/new/app">
+          {currentProject?.billing_enabled && !hasPaymentEnabled ? (
             <Button
               alt
-              onClick={async () => {
-                await updateAppStep({ step: "stack-launch-start" });
+              onClick={() => {
+                setShowBillingModal(true);
               }}
               height="35px"
             >
-              Create a new application <Spacer inline x={1} />{" "}
+              Create a new application
+              <Spacer inline x={1} />{" "}
               <i className="material-icons" style={{ fontSize: "18px" }}>
                 east
               </i>
             </Button>
-          </PorterLink>
+          ) : (
+            <PorterLink to="/apps/new/app">
+              <Button
+                alt
+                onClick={async () => {
+                  await updateAppStep({ step: "stack-launch-start" });
+                }}
+                height="35px"
+              >
+                Create a new application
+                <Spacer inline x={1} />{" "}
+                <i className="material-icons" style={{ fontSize: "18px" }}>
+                  east
+                </i>
+              </Button>
+            </PorterLink>
+          )}
+          {showBillingModal && (
+            <BillingModal
+              back={() => setShowBillingModal(false)}
+              onCreate={() => {
+                history.push("/apps/new/app");
+              }}
+            />
+          )}
         </DashboardPlaceholder>
       );
     }
@@ -308,7 +338,6 @@ const Apps: React.FC = () => {
           ) : (
             <PorterLink to="/apps/new/app">
               <Button
-                disabled={currentProject?.sandbox_enabled && apps.length == 3}
                 onClick={async () => {
                   await updateAppStep({ step: "stack-launch-start" });
                 }}

+ 16 - 8
dashboard/src/main/home/modals/BillingModal.tsx

@@ -4,6 +4,10 @@ import { loadStripe } from "@stripe/stripe-js";
 import styled from "styled-components";
 
 import Heading from "components/form-components/Heading";
+import Link from "components/porter/Link";
+import Modal from "components/porter/Modal";
+import Spacer from "components/porter/Spacer";
+import Text from "components/porter/Text";
 
 import backArrow from "assets/back_arrow.png";
 
@@ -34,14 +38,18 @@ const BillingModal = ({ back, onCreate }) => {
   };
 
   return (
-    <>
+    <Modal closeModal={back}>
       <div id="checkout">
-        <ControlRow>
-          <Heading isAtTop={true}>Add Payment Method</Heading>
-          <BackButton onClick={back}>
-            <BackButtonImg src={backArrow} />
-          </BackButton>
-        </ControlRow>
+        <Text size={16}>Add Payment Method</Text>
+        <Spacer y={1} />
+        <Text color="helper">
+          A payment method is required to begin deploying applications on
+          Porter. You can learn more about our pricing{" "}
+          <Link target="_blank" to="https://porter.run/pricing">
+            here
+          </Link>
+        </Text>
+        <Spacer y={1} />
         <Elements
           stripe={stripePromise}
           options={options}
@@ -50,7 +58,7 @@ const BillingModal = ({ back, onCreate }) => {
           <PaymentSetupForm onCreate={onCreate}></PaymentSetupForm>
         </Elements>
       </div>
-    </>
+    </Modal>
   );
 };
 

+ 7 - 6
dashboard/src/main/home/modals/PaymentSetupForm.tsx

@@ -6,7 +6,9 @@ import {
 } from "@stripe/react-stripe-js";
 import styled from "styled-components";
 
+import Button from "components/porter/Button";
 import Error from "components/porter/Error";
+import Spacer from "components/porter/Spacer";
 import SaveButton from "components/SaveButton";
 import { useCreatePaymentMethod } from "lib/hooks/useStripe";
 
@@ -34,6 +36,7 @@ const PaymentSetupForm = ({ onCreate }: { onCreate: () => void }) => {
 
     // Create the setup intent in the server
     const clientSecret = await createPaymentMethod();
+    console.log(clientSecret);
 
     // Finally, confirm with Stripe so the payment method is saved
     const { error } = await stripe.confirmSetup({
@@ -52,12 +55,10 @@ const PaymentSetupForm = ({ onCreate }: { onCreate: () => void }) => {
   return (
     <form>
       <PaymentElement />
-      <SubmitButton
-        className="submit-button"
-        text={"Add Payment Method"}
-        disabled={!stripe || loading}
-        onClick={handleSubmit}
-      ></SubmitButton>
+      <Spacer y={1} />
+      <Button disabled={!stripe || loading} onClick={handleSubmit}>
+        Add payment method
+      </Button>
       {errorMessage && <Error message={errorMessage}></Error>}
     </form>
   );

+ 16 - 17
dashboard/src/main/home/project-settings/APITokensSection.tsx

@@ -1,23 +1,16 @@
 import React, { useContext, useEffect, useMemo, useState } from "react";
 import styled from "styled-components";
 
-import { InviteType } from "shared/types";
+import Heading from "components/form-components/Heading";
+import Helper from "components/form-components/Helper";
+import Loading from "components/Loading";
+import SaveButton from "components/SaveButton";
+
 import api from "shared/api";
 import { Context } from "shared/Context";
 
-import Loading from "components/Loading";
-import InputRow from "components/form-components/InputRow";
-import Helper from "components/form-components/Helper";
-import Heading from "components/form-components/Heading";
-import CopyToClipboard from "components/CopyToClipboard";
-import { Column } from "react-table";
-import Table from "components/OldTable";
-import RadioSelector from "components/RadioSelector";
 import CreateAPITokenForm from "./api-tokens/CreateAPITokenForm";
 import TokenList from "./api-tokens/TokenList";
-import SaveButton from "components/SaveButton";
-
-type Props = {};
 
 export type APITokenMeta = {
   created_at: string;
@@ -33,11 +26,11 @@ export type APIToken = APITokenMeta & {
   token?: string;
 };
 
-const APITokensSection: React.FunctionComponent<Props> = ({}) => {
+const APITokensSection: React.FC = () => {
   const { currentProject } = useContext(Context);
 
   const [isLoading, setIsLoading] = useState(true);
-  const [apiTokens, setAPITokens] = useState<Array<APITokenMeta>>([]);
+  const [apiTokens, setAPITokens] = useState<APITokenMeta[]>([]);
   const [shouldCreate, setShouldCreate] = useState(false);
   const [expanded, setExpanded] = useState("");
 
@@ -64,8 +57,12 @@ const APITokensSection: React.FunctionComponent<Props> = ({}) => {
   if (shouldCreate) {
     return (
       <CreateAPITokenForm
-        onCreate={() => setShouldCreate(false)}
-        back={() => setShouldCreate(false)}
+        onCreate={() => {
+          setShouldCreate(false);
+        }}
+        back={() => {
+          setShouldCreate(false);
+        }}
       />
     );
   }
@@ -99,7 +96,9 @@ const APITokensSection: React.FunctionComponent<Props> = ({}) => {
         <SaveButton
           makeFlush={true}
           clearPosition={true}
-          onClick={() => setShouldCreate(true)}
+          onClick={() => {
+            setShouldCreate(true);
+          }}
         >
           <i className="material-icons">add</i>
           Create API Token

+ 79 - 101
dashboard/src/main/home/project-settings/BillingPage.tsx

@@ -1,23 +1,26 @@
 import React, { useContext, useState } from "react";
 import styled from "styled-components";
 
-import Heading from "components/form-components/Heading";
 import Loading from "components/Loading";
+import Button from "components/porter/Button";
+import Container from "components/porter/Container";
+import Fieldset from "components/porter/Fieldset";
 import Icon from "components/porter/Icon";
+import Spacer from "components/porter/Spacer";
 import Text from "components/porter/Text";
-import SaveButton from "components/SaveButton";
-import { usePaymentMethods } from "lib/hooks/useStripe";
+import {
+  checkIfProjectHasPayment,
+  usePaymentMethods,
+} from "lib/hooks/useStripe";
 
 import { Context } from "shared/Context";
 import cardIcon from "assets/credit-card.svg";
 import trashIcon from "assets/trash.png";
 
 import BillingModal from "../modals/BillingModal";
-import BillingDeleteConsent from "./BillingDeleteConsent";
 
-function BillingPage() {
-  const { currentProject } = useContext(Context);
-  const [showBillingDeleteModal, setShowBillingDeleteModal] = useState(false);
+function BillingPage(): JSX.Element {
+  const { setCurrentOverlay } = useContext(Context);
   const [shouldCreate, setShouldCreate] = useState(false);
   const {
     paymentMethodList,
@@ -26,120 +29,95 @@ function BillingPage() {
     isDeleting,
   } = usePaymentMethods();
 
+  const { refetchPaymentEnabled } = checkIfProjectHasPayment();
+
   const onCreate = async () => {
     setShouldCreate(false);
     refetchPaymentMethods();
+    refetchPaymentEnabled();
+  };
+
+  const onDelete = async (paymentMethodId: string) => {
+    deletePaymentMethod(paymentMethodId);
+    refetchPaymentEnabled();
   };
 
   if (shouldCreate) {
     return (
-      <BillingModal
-        onCreate={onCreate}
-        back={() => setShouldCreate(false)}
-        project_id={currentProject?.id}
-      />
+      <BillingModal onCreate={onCreate} back={() => setShouldCreate(false)} />
     );
   }
 
   return (
-    <div style={{ height: "1000px" }}>
-      <BillingModalWrapper>
-        <Heading isAtTop={true}>Payment methods</Heading>
-        <Text>This displays all configured payment methods</Text>
-        <PaymentMethodListWrapper>
-          {paymentMethodList.map((paymentMethod, idx) => {
-            return (
-              <PaymentMethodContainer key={idx}>
-                <Container>
+    <>
+      <Text size={16}>Payment methods</Text>
+      <Spacer y={1} />
+      <Text color="helper">
+        Manage the payment methods associated with this project.
+      </Text>
+      <Spacer y={1} />
+      {paymentMethodList.map((paymentMethod, idx) => {
+        return (
+          <>
+            <Fieldset key={idx}>
+              <Container row spaced>
+                <Container row>
                   <Icon src={cardIcon} height={"14px"} />
-                  <PaymentMethodText>
+                  <Spacer inline x={1} />
+                  <Text color="helper">
                     **** **** **** {paymentMethod.last4}
-                  </PaymentMethodText>
-                  <ExpirationText>
+                  </Text>
+                  <Spacer inline x={1} />
+                  <Text color="helper">
                     Expires: {paymentMethod.exp_month}/{paymentMethod.exp_year}
-                  </ExpirationText>
-                  <DeleteButtonContainer>
-                    {isDeleting ? (
-                      <Loading />
-                    ) : (
-                      <DeleteButton
-                        onClick={() => setShowBillingDeleteModal(true)}
-                      >
-                        <Icon src={trashIcon} height={"14px"} />
-                      </DeleteButton>
-                    )}
-                  </DeleteButtonContainer>
-                  <BillingDeleteConsent
-                    setShowModal={setShowBillingDeleteModal}
-                    show={showBillingDeleteModal}
-                    onDelete={() => deletePaymentMethod(paymentMethod.id)}
-                  />
+                  </Text>
+                  <Spacer inline x={1} />
                 </Container>
-              </PaymentMethodContainer>
-            );
-          })}
-        </PaymentMethodListWrapper>
-        <SaveButtonContainer>
-          <SaveButton
-            makeFlush={true}
-            clearPosition={true}
-            onClick={() => setShouldCreate(true)}
-          >
-            <i className="material-icons">add</i>
-            Add Payment Method
-          </SaveButton>
-        </SaveButtonContainer>
-      </BillingModalWrapper>
-    </div>
+                <DeleteButtonContainer>
+                  {isDeleting ? (
+                    <Loading />
+                  ) : (
+                    <DeleteButton
+                      onClick={() => {
+                        setCurrentOverlay({
+                          message: `Are you sure you want to remove this payment method?`,
+                          onYes: () => {
+                            deletePaymentMethod(paymentMethod.id);
+                            setCurrentOverlay(null);
+                          },
+                          onNo: () => {
+                            setCurrentOverlay(null);
+                          },
+                        });
+                      }}
+                    >
+                      <Icon src={trashIcon} height={"18px"} />
+                    </DeleteButton>
+                  )}
+                </DeleteButtonContainer>
+              </Container>
+            </Fieldset>
+            <Spacer y={1} />
+          </>
+        );
+      })}
+      <Button
+        onClick={() => {
+          setShouldCreate(true);
+        }}
+      >
+        <I className="material-icons">add</I>
+        Add Payment Method
+      </Button>
+    </>
   );
 }
 
 export default BillingPage;
 
-const PaymentMethodListWrapper = styled.div`
-  width: 100%;
-  max-height: 500px;
-  overflow-y: auto;
-`;
-
-const BillingModalWrapper = styled.div`
-  width: 60%;
-  min-width: 600px;
-`;
-
-const SaveButtonContainer = styled.div`
-  position: relative;
-  margin-top: 20px;
-`;
-
-const PaymentMethodContainer = styled.div`
-  color: #aaaabb;
-  border-radius: 5px;
-  padding: 10px;
-  display: block;
-  width: 100%;
-  border-radius: 5px;
-  background: ${(props) => props.theme.fg};
-  border: 1px solid ${({ theme }) => theme.border};
-  margin-bottom: 10px;
-  margin-top: 10px;
-`;
-
-const Container = styled.div`
-  padding: 5px;
-  display: flex;
-  justify-content: space-around;
-  align-items: center;
-`;
-
-const PaymentMethodText = styled.span`
-  font-size: 0.8em;
-  margin-right: 5px;
-`;
-
-const ExpirationText = styled.span`
-  font-size: 0.8em;
-  margin-right: 5px;
+const I = styled.i`
+  font-size: 18px;
+  margin-right: 10px;
 `;
 
 const DeleteButton = styled.div`

+ 6 - 6
dashboard/src/main/home/project-settings/ProjectSettings.tsx

@@ -85,12 +85,12 @@ function ProjectSettings(props: any) {
         });
       }
 
-      if (currentProject?.billing_enabled) {
-        tabOpts.push({
-          value: "billing",
-          label: "Billing",
-        });
-      }
+      // if (currentProject?.billing_enabled) {
+      tabOpts.push({
+        value: "billing",
+        label: "Billing",
+      });
+      // }
 
       tabOpts.push({
         value: "additional-settings",

+ 62 - 58
dashboard/src/shared/api.tsx

@@ -371,8 +371,9 @@ const getFeedEvents = baseApi<
   }
 >("GET", (pathParams) => {
   const { project_id, cluster_id, stack_name, page } = pathParams;
-  return `/api/projects/${project_id}/clusters/${cluster_id}/applications/${stack_name}/events?page=${page || 1
-    }`;
+  return `/api/projects/${project_id}/clusters/${cluster_id}/applications/${stack_name}/events?page=${
+    page || 1
+  }`;
 });
 
 const createEnvironment = baseApi<
@@ -860,9 +861,11 @@ const detectBuildpack = baseApi<
     branch: string;
   }
 >("GET", (pathParams) => {
-  return `/api/projects/${pathParams.project_id}/gitrepos/${pathParams.git_repo_id
-    }/repos/${pathParams.kind}/${pathParams.owner}/${pathParams.name
-    }/${encodeURIComponent(pathParams.branch)}/buildpack/detect`;
+  return `/api/projects/${pathParams.project_id}/gitrepos/${
+    pathParams.git_repo_id
+  }/repos/${pathParams.kind}/${pathParams.owner}/${
+    pathParams.name
+  }/${encodeURIComponent(pathParams.branch)}/buildpack/detect`;
 });
 
 const detectGitlabBuildpack = baseApi<
@@ -893,9 +896,11 @@ const getBranchContents = baseApi<
     branch: string;
   }
 >("GET", (pathParams) => {
-  return `/api/projects/${pathParams.project_id}/gitrepos/${pathParams.git_repo_id
-    }/repos/${pathParams.kind}/${pathParams.owner}/${pathParams.name
-    }/${encodeURIComponent(pathParams.branch)}/contents`;
+  return `/api/projects/${pathParams.project_id}/gitrepos/${
+    pathParams.git_repo_id
+  }/repos/${pathParams.kind}/${pathParams.owner}/${
+    pathParams.name
+  }/${encodeURIComponent(pathParams.branch)}/contents`;
 });
 
 const getProcfileContents = baseApi<
@@ -911,9 +916,11 @@ const getProcfileContents = baseApi<
     branch: string;
   }
 >("GET", (pathParams) => {
-  return `/api/projects/${pathParams.project_id}/gitrepos/${pathParams.git_repo_id
-    }/repos/${pathParams.kind}/${pathParams.owner}/${pathParams.name
-    }/${encodeURIComponent(pathParams.branch)}/procfile`;
+  return `/api/projects/${pathParams.project_id}/gitrepos/${
+    pathParams.git_repo_id
+  }/repos/${pathParams.kind}/${pathParams.owner}/${
+    pathParams.name
+  }/${encodeURIComponent(pathParams.branch)}/procfile`;
 });
 
 const getPorterYamlContents = baseApi<
@@ -929,9 +936,11 @@ const getPorterYamlContents = baseApi<
     branch: string;
   }
 >("GET", (pathParams) => {
-  return `/api/projects/${pathParams.project_id}/gitrepos/${pathParams.git_repo_id
-    }/repos/${pathParams.kind}/${pathParams.owner}/${pathParams.name
-    }/${encodeURIComponent(pathParams.branch)}/porteryaml`;
+  return `/api/projects/${pathParams.project_id}/gitrepos/${
+    pathParams.git_repo_id
+  }/repos/${pathParams.kind}/${pathParams.owner}/${
+    pathParams.name
+  }/${encodeURIComponent(pathParams.branch)}/porteryaml`;
 });
 
 const parsePorterYaml = baseApi<
@@ -991,30 +1000,32 @@ const getBranchHead = baseApi<
     branch: string;
   }
 >("GET", (pathParams) => {
-  return `/api/projects/${pathParams.project_id}/gitrepos/${pathParams.git_repo_id
-    }/repos/${pathParams.kind}/${pathParams.owner}/${pathParams.name
-    }/${encodeURIComponent(pathParams.branch)}/head`;
+  return `/api/projects/${pathParams.project_id}/gitrepos/${
+    pathParams.git_repo_id
+  }/repos/${pathParams.kind}/${pathParams.owner}/${
+    pathParams.name
+  }/${encodeURIComponent(pathParams.branch)}/head`;
 });
 
 const createApp = baseApi<
   | {
-    name: string;
-    deployment_target_id: string;
-    type: "github";
-    git_repo_id: number;
-    git_branch: string;
-    git_repo_name: string;
-    porter_yaml_path: string;
-  }
+      name: string;
+      deployment_target_id: string;
+      type: "github";
+      git_repo_id: number;
+      git_branch: string;
+      git_repo_name: string;
+      porter_yaml_path: string;
+    }
   | {
-    name: string;
-    deployment_target_id: string;
-    type: "docker-registry";
-    image: {
-      repository: string;
-      tag: string;
-    };
-  },
+      name: string;
+      deployment_target_id: string;
+      type: "docker-registry";
+      image: {
+        repository: string;
+        tag: string;
+      };
+    },
   {
     project_id: number;
     cluster_id: number;
@@ -2229,9 +2240,11 @@ const getEnvGroup = baseApi<
     version?: number;
   }
 >("GET", (pathParams) => {
-  return `/api/projects/${pathParams.id}/clusters/${pathParams.cluster_id
-    }/namespaces/${pathParams.namespace}/envgroup?name=${pathParams.name}${pathParams.version ? "&version=" + pathParams.version : ""
-    }`;
+  return `/api/projects/${pathParams.id}/clusters/${
+    pathParams.cluster_id
+  }/namespaces/${pathParams.namespace}/envgroup?name=${pathParams.name}${
+    pathParams.version ? "&version=" + pathParams.version : ""
+  }`;
 });
 
 const getConfigMap = baseApi<
@@ -2561,17 +2574,6 @@ const getUsage = baseApi<{}, { project_id: number }>(
   ({ project_id }) => `/api/projects/${project_id}/usage`
 );
 
-// Used for billing purposes
-const getCustomerToken = baseApi<{}, { project_id: number }>(
-  "GET",
-  ({ project_id }) => `/api/projects/${project_id}/billing/token`
-);
-
-const getHasBilling = baseApi<{}, { project_id: number }>(
-  "GET",
-  ({ project_id }) => `/api/projects/${project_id}/billing`
-);
-
 const getOnboardingState = baseApi<{}, { project_id: number }>(
   "GET",
   ({ project_id }) => `/api/projects/${project_id}/onboarding`
@@ -3427,16 +3429,18 @@ const removeStackEnvGroup = baseApi<
 // Billing
 const checkBillingCustomerExists = baseApi<
   {
-    user_email?: string,
+    user_email?: string;
   },
   {
     project_id?: number;
   }
->(
-  "POST",
-  ({ project_id }) =>
-    `/api/projects/${project_id}/billing/customer`
+>("POST", ({ project_id }) => `/api/projects/${project_id}/billing/customer`);
+
+const getHasBilling = baseApi<{}, { project_id: number }>(
+  "GET",
+  ({ project_id }) => `/api/projects/${project_id}/billing`
 );
+
 const listPaymentMethod = baseApi<
   {},
   {
@@ -3444,9 +3448,9 @@ const listPaymentMethod = baseApi<
   }
 >(
   "GET",
-  ({ project_id }) =>
-    `/api/projects/${project_id}/billing/payment_method`
+  ({ project_id }) => `/api/projects/${project_id}/billing/payment_method`
 );
+
 const addPaymentMethod = baseApi<
   {},
   {
@@ -3454,9 +3458,9 @@ const addPaymentMethod = baseApi<
   }
 >(
   "POST",
-  ({ project_id }) =>
-    `/api/projects/${project_id}/billing/payment_method`
+  ({ project_id }) => `/api/projects/${project_id}/billing/payment_method`
 );
+
 const updatePaymentMethod = baseApi<
   {},
   {
@@ -3468,6 +3472,7 @@ const updatePaymentMethod = baseApi<
   ({ project_id, payment_method_id }) =>
     `/api/projects/${project_id}/billing/payment_method/${payment_method_id}`
 );
+
 const deletePaymentMethod = baseApi<
   {},
   {
@@ -3480,7 +3485,7 @@ const deletePaymentMethod = baseApi<
     `/api/projects/${project_id}/billing/payment_method/${payment_method_id}`
 );
 
-const getGithubStatus = baseApi<{}, {}>("GET", ({ }) => `/api/status/github`);
+const getGithubStatus = baseApi<{}, {}>("GET", ({}) => `/api/status/github`);
 
 const createSecretAndOpenGitHubPullRequest = baseApi<
   {
@@ -3744,7 +3749,6 @@ export default {
   getPolicyDocument,
   createWebhookToken,
   getUsage,
-  getCustomerToken,
   getHasBilling,
   getOnboardingState,
   saveOnboardingState,