useStripe.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import { useContext, useState } from "react";
  2. import { useQuery } from "@tanstack/react-query";
  3. import { z } from "zod";
  4. import {
  5. ClientSecretResponse,
  6. PaymentMethodList,
  7. PaymentMethodValidator,
  8. } from "lib/billing/types";
  9. import api from "shared/api";
  10. import { Context } from "shared/Context";
  11. type TUsePaymentMethod = {
  12. paymentMethodList: PaymentMethodList;
  13. refetchPaymentMethods: any;
  14. isDeleting: boolean;
  15. deletePaymentMethod: (paymentMethodId: string) => Promise<void>;
  16. };
  17. type TCreatePaymentMethod = {
  18. createPaymentMethod: () => Promise<string>;
  19. };
  20. type TCheckHasPaymentEnabled = {
  21. hasPaymentEnabled: boolean;
  22. refetchPaymentEnabled: any;
  23. };
  24. export const usePaymentMethods = (): TUsePaymentMethod => {
  25. const { user, currentProject } = useContext(Context);
  26. // State has be shared so that payment methods can be removed
  27. // from the Billing page once they are deleted
  28. const [paymentMethodList, setPaymentMethodList] = useState<PaymentMethodList>(
  29. []
  30. );
  31. const [isDeleting, setIsDeleting] = useState<boolean>(false);
  32. // Fetch list of payment methods
  33. const paymentMethodReq = useQuery(
  34. ["getPaymentMethods", currentProject?.id],
  35. async () => {
  36. if (!currentProject?.id || currentProject.id === -1) {
  37. return;
  38. }
  39. await api.checkBillingCustomerExists(
  40. "<token>",
  41. { user_email: user?.email },
  42. { project_id: currentProject?.id }
  43. );
  44. const listResponse = await api.listPaymentMethod(
  45. "<token>",
  46. {},
  47. { project_id: currentProject?.id }
  48. );
  49. const data = PaymentMethodValidator.array().parse(listResponse.data);
  50. setPaymentMethodList(data);
  51. return data;
  52. }
  53. );
  54. // Delete list of payment methods
  55. const deletePaymentMethod = async (paymentMethodId: string) => {
  56. if (!currentProject?.id) {
  57. throw new Error("Project ID is missing");
  58. }
  59. if (!paymentMethodId) {
  60. throw new Error("Payment Method ID is missing");
  61. }
  62. setIsDeleting(true);
  63. const resp = await api.deletePaymentMethod(
  64. "<token>",
  65. {},
  66. { project_id: currentProject?.id, payment_method_id: paymentMethodId }
  67. );
  68. if (resp.status !== 200) {
  69. throw new Error("Failed to delete payment method");
  70. }
  71. setPaymentMethodList(
  72. paymentMethodList.filter(
  73. (paymentMethod) => paymentMethod.id !== paymentMethodId
  74. )
  75. );
  76. setIsDeleting(false);
  77. };
  78. return {
  79. paymentMethodList,
  80. refetchPaymentMethods: paymentMethodReq.refetch,
  81. isDeleting,
  82. deletePaymentMethod,
  83. };
  84. };
  85. export const useCreatePaymentMethod = (): TCreatePaymentMethod => {
  86. const { currentProject } = useContext(Context);
  87. const createPaymentMethod = async () => {
  88. const resp = await api.addPaymentMethod(
  89. "<token>",
  90. {},
  91. { project_id: currentProject?.id }
  92. );
  93. const clientSecret = ClientSecretResponse.parse(resp.data);
  94. return clientSecret;
  95. };
  96. return {
  97. createPaymentMethod,
  98. };
  99. };
  100. export const checkIfProjectHasPayment = (): TCheckHasPaymentEnabled => {
  101. const { currentProject } = useContext(Context);
  102. if (!currentProject?.id) {
  103. throw new Error("Project ID is missing");
  104. }
  105. // Fetch list of payment methods
  106. const paymentEnabledReq = useQuery(
  107. ["checkPaymentEnabled", currentProject?.id],
  108. async () => {
  109. const res = await api.getHasBilling(
  110. "<token>",
  111. {},
  112. { project_id: currentProject.id }
  113. );
  114. const data = z.boolean().parse(res.data);
  115. return data;
  116. }
  117. );
  118. return {
  119. hasPaymentEnabled: paymentEnabledReq.data ?? false,
  120. refetchPaymentEnabled: paymentEnabledReq.refetch,
  121. };
  122. };