Skip to content

Commit 82c0cd0

Browse files
authored
Update settings page to support updating subscription (#123)
1 parent 6a6195b commit 82c0cd0

File tree

2 files changed

+140
-6
lines changed

2 files changed

+140
-6
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { useEffect, useState } from "react";
2+
3+
import {
4+
TextField,
5+
Button,
6+
FormGroup,
7+
InputLabel,
8+
Paper,
9+
Stack,
10+
Dialog,
11+
DialogTitle,
12+
DialogContent,
13+
DialogActions,
14+
MenuItem,
15+
Select,
16+
} from "@mui/material";
17+
import { axios } from "../data/axios";
18+
import { LoadingButton } from "@mui/lab";
19+
import { enqueueSnackbar } from "notistack";
20+
21+
const SubscriptionUpdateModal = ({ open, handleCloseCb, userEmail }) => {
22+
const [subscriptionPrices, setSubscriptionPrices] = useState([]);
23+
const [subscription, setSubscription] = useState("");
24+
const [updateButtonLoading, setUpdateButtonLoading] = useState(false);
25+
const [updateButtonDisabled, setUpdateButtonDisabled] = useState(false);
26+
const [cancelButtonDisabled, setCancelButtonDisabled] = useState(false);
27+
28+
useEffect(() => {
29+
axios()
30+
.get("/api/subscriptions/prices")
31+
.then((res) => {
32+
setSubscriptionPrices(res.data.prices || []);
33+
})
34+
.catch((err) => {
35+
enqueueSnackbar("Error loading subscription prices", {
36+
variant: "error",
37+
});
38+
});
39+
}, []);
40+
41+
return (
42+
<Dialog open={open} onClose={handleCloseCb} fullWidth>
43+
<DialogTitle>{"Manage Subscription"}</DialogTitle>
44+
<DialogContent>
45+
<FormGroup>
46+
<Stack spacing={2} sx={{ textAlign: "left", margin: "10px" }}>
47+
<Paper sx={{ marginBottom: "30px" }}>
48+
<TextField
49+
label="Email"
50+
value={userEmail}
51+
fullWidth
52+
variant="outlined"
53+
/>
54+
</Paper>
55+
<Paper sx={{ marginBottom: "30px" }}>
56+
<InputLabel id="subscription-id">Subscription</InputLabel>
57+
<Select
58+
labelId="subscription-id"
59+
value={subscription}
60+
label="Subscription"
61+
fullWidth
62+
variant="outlined"
63+
onChange={(e) => {
64+
setSubscription(e.target.value);
65+
}}
66+
>
67+
{subscriptionPrices.map((subscriptionPrice) => (
68+
<MenuItem
69+
key={subscriptionPrice.id}
70+
value={subscriptionPrice.id}
71+
>
72+
{subscriptionPrice.name}
73+
</MenuItem>
74+
))}
75+
</Select>
76+
</Paper>
77+
</Stack>
78+
</FormGroup>
79+
</DialogContent>
80+
<DialogActions>
81+
<Button disabled={cancelButtonDisabled} onClick={handleCloseCb}>
82+
Cancel
83+
</Button>
84+
<LoadingButton
85+
disabled={updateButtonDisabled || !subscription}
86+
loading={updateButtonLoading}
87+
onClick={() => {
88+
setCancelButtonDisabled(true);
89+
setUpdateButtonDisabled(true);
90+
setUpdateButtonLoading(true);
91+
axios()
92+
.post("/api/subscriptions/checkout", {
93+
price_id: subscription,
94+
})
95+
.then((res) => {
96+
enqueueSnackbar("Loading Checkout Page", {
97+
variant: "success",
98+
});
99+
window.location.href = res.data.checkout_session_url;
100+
})
101+
.catch((err) => {})
102+
.finally(() => {
103+
setCancelButtonDisabled(false);
104+
setUpdateButtonDisabled(false);
105+
setUpdateButtonLoading(false);
106+
});
107+
}}
108+
variant="contained"
109+
>
110+
Update
111+
</LoadingButton>
112+
</DialogActions>
113+
</Dialog>
114+
);
115+
};
116+
117+
export default SubscriptionUpdateModal;

llmstack/client/src/pages/setting.jsx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ import {
1212
Paper,
1313
Stack,
1414
} from "@mui/material";
15+
1516
import { styled } from "@mui/material/styles";
1617
import FileUpload from "@mui/icons-material/FileUpload";
1718
import ContentCopy from "@mui/icons-material/ContentCopy";
1819
import { useEffect, useState } from "react";
1920
import { enqueueSnackbar } from "notistack";
2021
import Connections from "../components/Connections";
22+
import SubscriptionUpdateModal from "../components/SubscriptionUpdateModal";
2123
import { fetchData, patchData } from "./dataUtil";
2224
import { organizationState, profileFlagsState } from "../data/atoms";
2325
import { useRecoilValue } from "recoil";
@@ -140,6 +142,8 @@ const SettingPage = () => {
140142
logo: "",
141143
});
142144
const [loading, setLoading] = useState(true);
145+
const [subscriptionUpdateModalOpen, setSubscriptionUpdateModalOpen] =
146+
useState(false);
143147
const [updateKeys, setUpdateKeys] = useState(new Set());
144148
const profileFlags = useRecoilValue(profileFlagsState);
145149
const organization = useRecoilValue(organizationState);
@@ -169,6 +173,13 @@ const SettingPage = () => {
169173
setLoading(false);
170174
},
171175
);
176+
177+
const searchParams = new URLSearchParams(window.location.search);
178+
if (searchParams.get("showNotification")) {
179+
enqueueSnackbar(searchParams.get("notificationMessage") || "", {
180+
variant: searchParams.get("notificationType") || "info",
181+
});
182+
}
172183
}, []);
173184

174185
const handleUpdate = (update_keys) => {
@@ -386,19 +397,16 @@ const SettingPage = () => {
386397
{process.env.REACT_APP_ENABLE_SUBSCRIPTION_MANAGEMENT ===
387398
"true" && (
388399
<Button
389-
href={`${
390-
process.env.REACT_APP_SUBSCRIPTION_MANAGEMENT_URL
391-
}?prefilled_email=${encodeURIComponent(
392-
formData.user_email,
393-
)}`}
394-
target="_blank"
395400
variant="outlined"
396401
style={{
397402
marginRight: "10px",
398403
display: profileFlags.IS_ORGANIZATION_MEMBER
399404
? "none"
400405
: "inherit",
401406
}}
407+
onClick={() => {
408+
setSubscriptionUpdateModalOpen(true);
409+
}}
402410
>
403411
Manage Subscription
404412
</Button>
@@ -411,6 +419,15 @@ const SettingPage = () => {
411419
</Grid>
412420
</Grid>
413421
)}
422+
{subscriptionUpdateModalOpen && (
423+
<SubscriptionUpdateModal
424+
open={subscriptionUpdateModalOpen}
425+
handleCloseCb={() => {
426+
setSubscriptionUpdateModalOpen(false);
427+
}}
428+
userEmail={formData.user_email}
429+
/>
430+
)}
414431
</div>
415432
);
416433
};

0 commit comments

Comments
 (0)