Skip to content

Commit e44fd52

Browse files
removed InitializeSubscription hook + added SubscriptionContext to handle customer, products
1 parent 3bee7f1 commit e44fd52

File tree

13 files changed

+397
-318
lines changed

13 files changed

+397
-318
lines changed

client/packages/lowcoder/src/api/subscriptionApi.ts

Lines changed: 6 additions & 240 deletions
Original file line numberDiff line numberDiff line change
@@ -1,130 +1,16 @@
11
import Api from "api/api";
22
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
33
import { useDispatch, useSelector } from "react-redux";
4-
import { getUser, getCurrentUser } from "redux/selectors/usersSelectors";
54
import { useEffect, useState} from "react";
65
import { calculateFlowCode } from "./apiUtils";
7-
import { getDeploymentId } from "@lowcoder-ee/redux/selectors/configSelectors";
86
import { fetchOrgUsersAction } from "redux/reduxActions/orgActions";
97
import { getOrgUsers } from "redux/selectors/orgSelectors";
108
import { AppState } from "@lowcoder-ee/redux/reducers";
11-
import { SubscriptionProducts } from "@lowcoder-ee/constants/subscriptionConstants";
12-
import { getFetchSubscriptionsFinished, getSubscriptions, getSubscriptionsError } from "@lowcoder-ee/redux/selectors/subscriptionSelectors";
13-
14-
// Interfaces
15-
export interface CustomerAddress {
16-
line1: string;
17-
line2: string;
18-
city: string;
19-
state: string;
20-
country: string;
21-
postalCode: string;
22-
}
23-
24-
export interface LowcoderNewCustomer {
25-
hostname: string;
26-
hostId: string;
27-
email: string;
28-
orgId: string;
29-
userId: string;
30-
userName: string;
31-
type: string;
32-
companyName: string;
33-
address?: CustomerAddress;
34-
}
35-
36-
export interface LowcoderSearchCustomer {
37-
hostname: string;
38-
hostId: string;
39-
email: string;
40-
orgId: string;
41-
userId: string;
42-
}
43-
44-
interface LowcoderMetadata {
45-
lowcoder_host: string;
46-
lowcoder_hostId: string;
47-
lowcoder_orgId: string;
48-
lowcoder_type: string;
49-
lowcoder_userId: string;
50-
}
51-
52-
export interface StripeCustomer {
53-
id: string;
54-
object: string;
55-
address?: object | null;
56-
balance: number;
57-
created: number;
58-
currency: string | null;
59-
default_source: string | null;
60-
delinquent: boolean;
61-
description: string | null;
62-
discount: string | null;
63-
email: string;
64-
invoice_prefix: string;
65-
invoice_settings: object | null;
66-
livemode: boolean;
67-
metadata: LowcoderMetadata;
68-
name: string;
69-
phone: string | null;
70-
preferred_locales: string[];
71-
shipping: string | null;
72-
tax_exempt: string;
73-
test_clock: string | null;
74-
}
75-
76-
export interface Pricing {
77-
type: string;
78-
amount: string;
79-
}
80-
81-
export interface Product {
82-
title?: string;
83-
description?: string;
84-
image?: string;
85-
pricingType: string;
86-
product: string;
87-
activeSubscription: boolean;
88-
accessLink: string;
89-
subscriptionId: string;
90-
checkoutLink: string;
91-
checkoutLinkDataLoaded?: boolean;
92-
type?: string;
93-
quantity_entity?: string;
94-
}
95-
96-
export interface SubscriptionItem {
97-
id: string;
98-
object: string;
99-
plan: {
100-
id: string;
101-
product: string;
102-
};
103-
quantity: number;
104-
}
105-
106-
export interface Subscription {
107-
id: string;
108-
collection_method: string;
109-
current_period_end: number;
110-
current_period_start: number;
111-
product: string;
112-
currency: string;
113-
interval: string;
114-
tiers_mode: string;
115-
status: string;
116-
start_date: number;
117-
quantity: number;
118-
billing_scheme: string;
119-
price: string;
120-
}
121-
122-
export interface SubscriptionsData {
123-
subscriptions: Subscription[];
124-
subscriptionDataLoaded: boolean;
125-
subscriptionDataError: boolean;
126-
loading: boolean;
127-
}
9+
import type {
10+
LowcoderNewCustomer,
11+
LowcoderSearchCustomer,
12+
StripeCustomer,
13+
} from "@lowcoder-ee/constants/subscriptionConstants";
12814

12915
export type ResponseType = {
13016
response: any;
@@ -276,7 +162,7 @@ export const getProducts = async () => {
276162
};
277163
try {
278164
const result = await SubscriptionApi.secureRequest(apiBody);
279-
return result?.data as any;
165+
return result?.data?.data as any[];
280166
} catch (error) {
281167
console.error("Error fetching product:", error);
282168
throw error;
@@ -382,124 +268,4 @@ export const useOrgUserCount = (orgId: string) => {
382268
return userCount;
383269
};
384270

385-
export const InitializeSubscription = () => {
386-
const [customer, setCustomer] = useState<StripeCustomer | null>(null);
387-
const [isCreatingCustomer, setIsCreatingCustomer] = useState<boolean>(false); // Track customer creation
388-
const [customerDataError, setCustomerDataError] = useState<boolean>(false);
389-
const [checkoutLinkDataLoaded, setCheckoutLinkDataLoaded] = useState<boolean>(false);
390-
const [checkoutLinkDataError, setCheckoutLinkDataError] = useState<boolean>(false);
391-
const [products, setProducts] = useState<Product[]>(SubscriptionProducts);
392-
393-
const user = useSelector(getUser);
394-
const currentUser = useSelector(getCurrentUser);
395-
const deploymentId = useSelector(getDeploymentId);
396-
const subscriptions = useSelector(getSubscriptions);
397-
const subscriptionDataLoaded = useSelector(getFetchSubscriptionsFinished);
398-
const subscriptionDataError = useSelector(getSubscriptionsError)
399-
const currentOrg = user.orgs.find(org => org.id === user.currentOrgId);
400-
const orgID = user.currentOrgId;
401-
const domain = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port : '');
402-
const admin = user.orgRoleMap.get(orgID) === "admin" ? "admin" : "member";
403-
const dispatch = useDispatch();
404-
405-
const userCount = useOrgUserCount(orgID);
406-
407-
const subscriptionSearchCustomer: LowcoderSearchCustomer = {
408-
hostname: domain,
409-
hostId: deploymentId,
410-
email: currentUser.email,
411-
orgId: orgID,
412-
userId: user.id,
413-
};
414-
415-
const subscriptionNewCustomer: LowcoderNewCustomer = {
416-
hostname: domain,
417-
hostId: deploymentId,
418-
email: currentUser.email,
419-
orgId: orgID,
420-
userId: user.id,
421-
userName: user.username,
422-
type: admin,
423-
companyName: currentOrg?.name || "Unknown",
424-
};
425-
426-
useEffect(() => {
427-
const initializeCustomer = async () => {
428-
try {
429-
setIsCreatingCustomer(true);
430-
const existingCustomer = await searchCustomer(subscriptionSearchCustomer);
431-
if (existingCustomer != null) {
432-
setCustomer(existingCustomer);
433-
} else {
434-
const newCustomer = await createCustomer(subscriptionNewCustomer);
435-
setCustomer(newCustomer);
436-
}
437-
} catch (error) {
438-
setCustomerDataError(true);
439-
} finally {
440-
setIsCreatingCustomer(false);
441-
}
442-
};
443-
444-
if (Boolean(deploymentId)) {
445-
initializeCustomer();
446-
}
447-
}, [deploymentId]);
448-
449-
useEffect(() => {
450-
const prepareCheckout = async () => {
451-
if (subscriptionDataLoaded && userCount > 0) { // Ensure user count is available
452-
try {
453-
console.log("Total Users in Organization:", userCount);
454-
455-
const updatedProducts = await Promise.all(
456-
products.map(async (product) => {
457-
const matchingSubscription = subscriptions.find(
458-
(sub) => sub.price === product.accessLink
459-
);
460-
461-
if (matchingSubscription) {
462-
return {
463-
...product,
464-
activeSubscription: true,
465-
checkoutLinkDataLoaded: true,
466-
subscriptionId: matchingSubscription.id,
467-
};
468-
} else {
469-
// Use the user count to set the quantity for checkout link
470-
const checkoutLink = await createCheckoutLink(customer!, product.accessLink, userCount);
471-
return {
472-
...product,
473-
activeSubscription: false,
474-
checkoutLink: checkoutLink ? checkoutLink.url : "",
475-
checkoutLinkDataLoaded: true,
476-
};
477-
}
478-
})
479-
);
480-
setProducts(updatedProducts);
481-
setCheckoutLinkDataError(true);
482-
} catch (error) {
483-
setCheckoutLinkDataError(true);
484-
}
485-
}
486-
};
487-
488-
prepareCheckout();
489-
}, [subscriptionDataLoaded, customer, userCount]);
490-
491-
return {
492-
customer,
493-
isCreatingCustomer,
494-
customerDataError,
495-
subscriptions,
496-
subscriptionDataLoaded,
497-
subscriptionDataError,
498-
checkoutLinkDataLoaded,
499-
checkoutLinkDataError,
500-
products,
501-
admin,
502-
};
503-
};
504-
505271
export default SubscriptionApi;

client/packages/lowcoder/src/constants/subscriptionConstants.ts

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export enum SubscriptionProductsEnum {
1919
GITREPOS = 'git-repos',
2020
}
2121

22-
export const SubscriptionProducts = [
22+
export const InitSubscriptionProducts = [
2323
{
2424
pricingType: "Monthly, per User",
2525
activeSubscription: false,
@@ -53,4 +53,102 @@ export const SubscriptionProducts = [
5353
type: "org",
5454
quantity_entity: "singleItem",
5555
},
56-
]
56+
]
57+
58+
export interface Subscription {
59+
id: string;
60+
collection_method: string;
61+
current_period_end: number;
62+
current_period_start: number;
63+
product: string;
64+
currency: string;
65+
interval: string;
66+
tiers_mode: string;
67+
status: string;
68+
start_date: number;
69+
quantity: number;
70+
billing_scheme: string;
71+
price: string;
72+
}
73+
74+
export interface SubscriptionProduct {
75+
title?: string;
76+
description?: string;
77+
image?: string;
78+
pricingType: string;
79+
product: string;
80+
activeSubscription: boolean;
81+
accessLink: string;
82+
subscriptionId: string;
83+
checkoutLink: string;
84+
checkoutLinkDataLoaded?: boolean;
85+
type?: string;
86+
quantity_entity?: string;
87+
}
88+
89+
export interface CustomerAddress {
90+
line1: string;
91+
line2: string;
92+
city: string;
93+
state: string;
94+
country: string;
95+
postalCode: string;
96+
}
97+
98+
export interface LowcoderNewCustomer {
99+
hostname: string;
100+
hostId: string;
101+
email: string;
102+
orgId: string;
103+
userId: string;
104+
userName: string;
105+
type: string;
106+
companyName: string;
107+
address?: CustomerAddress;
108+
}
109+
110+
export interface LowcoderSearchCustomer {
111+
hostname: string;
112+
hostId: string;
113+
email: string;
114+
orgId: string;
115+
userId: string;
116+
}
117+
118+
interface LowcoderMetadata {
119+
lowcoder_host: string;
120+
lowcoder_hostId: string;
121+
lowcoder_orgId: string;
122+
lowcoder_type: string;
123+
lowcoder_userId: string;
124+
}
125+
126+
export interface StripeCustomer {
127+
id: string;
128+
object: string;
129+
address?: object | null;
130+
balance: number;
131+
created: number;
132+
currency: string | null;
133+
default_source: string | null;
134+
delinquent: boolean;
135+
description: string | null;
136+
discount: string | null;
137+
email: string;
138+
invoice_prefix: string;
139+
invoice_settings: object | null;
140+
livemode: boolean;
141+
metadata: LowcoderMetadata;
142+
name: string;
143+
phone: string | null;
144+
preferred_locales: string[];
145+
shipping: string | null;
146+
tax_exempt: string;
147+
test_clock: string | null;
148+
}
149+
150+
export interface Pricing {
151+
type: string;
152+
amount: string;
153+
}
154+

0 commit comments

Comments
 (0)