Skip to content

Commit 364938d

Browse files
committed
settings: create billing submenu similar to preferences
1 parent e107d42 commit 364938d

File tree

1 file changed

+129
-82
lines changed

1 file changed

+129
-82
lines changed

src/packages/frontend/account/account-page.tsx

Lines changed: 129 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,20 @@ import { UpgradesPage } from "./upgrades/upgrades-page";
8989

9090
export const ACCOUNT_SETTINGS_ICON_NAME: IconName = "settings";
9191

92+
const BILLING_MENU_KEYS = new Set([
93+
"subscriptions",
94+
"licenses",
95+
"payg",
96+
"upgrades",
97+
"purchases",
98+
"payments",
99+
"payment-methods",
100+
"statements",
101+
]);
102+
92103
function getParentMenuKey(key?: string): string | undefined {
93104
if (!key) return;
105+
if (BILLING_MENU_KEYS.has(key)) return "billing";
94106
const dashIndex = key.indexOf("-");
95107
if (dashIndex === -1) return;
96108
return key.slice(0, dashIndex);
@@ -323,85 +335,102 @@ export const AccountPage: React.FC = () => {
323335
items.push({ type: "divider" });
324336

325337
if (is_commercial) {
326-
items.push({
327-
key: "subscriptions",
328-
label: (
329-
<span>
330-
<Icon name="calendar" /> {intl.formatMessage(labels.subscriptions)}
331-
</span>
332-
),
333-
children: active_page === "subscriptions" && <SubscriptionsPage />,
334-
});
335-
items.push({
336-
key: "licenses",
337-
label: (
338-
<span>
339-
<Icon name="key" /> {intl.formatMessage(labels.licenses)}
340-
</span>
341-
),
342-
children: active_page === "licenses" && <LicensesPage />,
343-
});
344-
items.push({
345-
key: "payg",
346-
label: (
347-
<span>
348-
<Icon name="line-chart" />{" "}
349-
{intl.formatMessage(labels.pay_as_you_go)}
350-
</span>
351-
),
352-
children: active_page === "payg" && <PayAsYouGoPage />,
353-
});
354-
if (is_commercial && kucalc === KUCALC_COCALC_COM) {
355-
// these have been deprecated for ~ 5 years, but some customers still have them.
356-
items.push({
357-
key: "upgrades",
338+
const billingChildren = [
339+
{
340+
key: "subscriptions",
358341
label: (
359342
<span>
360-
<Icon name="arrow-circle-up" />{" "}
361-
{intl.formatMessage(labels.upgrades)}
343+
<Icon name="calendar" />{" "}
344+
{intl.formatMessage(labels.subscriptions)}
362345
</span>
363346
),
364-
children: active_page === "upgrades" && <UpgradesPage />,
365-
});
366-
}
367-
items.push({ type: "divider" });
368-
items.push({
369-
key: "purchases",
370-
label: (
371-
<span>
372-
<Icon name="money-check" /> {intl.formatMessage(labels.purchases)}
373-
</span>
374-
),
375-
children: active_page === "purchases" && <PurchasesPage />,
376-
});
377-
items.push({
378-
key: "payments",
379-
label: (
380-
<span>
381-
<Icon name="credit-card" /> {intl.formatMessage(labels.payments)}
382-
</span>
383-
),
384-
children: active_page === "payments" && <PaymentsPage />,
385-
});
386-
items.push({
387-
key: "payment-methods",
388-
label: (
389-
<span>
390-
<Icon name="credit-card" />{" "}
391-
{intl.formatMessage(labels.payment_methods)}
392-
</span>
393-
),
394-
children: active_page === "payment-methods" && <PaymentMethodsPage />,
395-
});
347+
children: active_page === "subscriptions" && <SubscriptionsPage />,
348+
},
349+
{
350+
key: "licenses",
351+
label: (
352+
<span>
353+
<Icon name="key" /> {intl.formatMessage(labels.licenses)}
354+
</span>
355+
),
356+
children: active_page === "licenses" && <LicensesPage />,
357+
},
358+
{
359+
key: "payg",
360+
label: (
361+
<span>
362+
<Icon name="line-chart" />{" "}
363+
{intl.formatMessage(labels.pay_as_you_go)}
364+
</span>
365+
),
366+
children: active_page === "payg" && <PayAsYouGoPage />,
367+
},
368+
...(is_commercial && kucalc === KUCALC_COCALC_COM
369+
? [
370+
{
371+
key: "upgrades",
372+
label: (
373+
<span>
374+
<Icon name="arrow-circle-up" />{" "}
375+
{intl.formatMessage(labels.upgrades)}
376+
</span>
377+
),
378+
children: active_page === "upgrades" && <UpgradesPage />,
379+
},
380+
]
381+
: []),
382+
{
383+
key: "purchases",
384+
label: (
385+
<span>
386+
<Icon name="money-check" />{" "}
387+
{intl.formatMessage(labels.purchases)}
388+
</span>
389+
),
390+
children: active_page === "purchases" && <PurchasesPage />,
391+
},
392+
{
393+
key: "payments",
394+
label: (
395+
<span>
396+
<Icon name="credit-card" />{" "}
397+
{intl.formatMessage(labels.payments)}
398+
</span>
399+
),
400+
children: active_page === "payments" && <PaymentsPage />,
401+
},
402+
{
403+
key: "payment-methods",
404+
label: (
405+
<span>
406+
<Icon name="credit-card" />{" "}
407+
{intl.formatMessage(labels.payment_methods)}
408+
</span>
409+
),
410+
children: active_page === "payment-methods" && (
411+
<PaymentMethodsPage />
412+
),
413+
},
414+
{
415+
key: "statements",
416+
label: (
417+
<span>
418+
<Icon name="calendar-week" />{" "}
419+
{intl.formatMessage(labels.statements)}
420+
</span>
421+
),
422+
children: active_page === "statements" && <StatementsPage />,
423+
},
424+
];
425+
396426
items.push({
397-
key: "statements",
427+
key: "billing",
398428
label: (
399429
<span>
400-
<Icon name="calendar-week" />{" "}
401-
{intl.formatMessage(labels.statements)}
430+
<Icon name="money-check" /> {intl.formatMessage(labels.billing)}
402431
</span>
403432
),
404-
children: active_page === "statements" && <StatementsPage />,
433+
children: billingChildren,
405434
});
406435
items.push({ type: "divider" });
407436
}
@@ -455,22 +484,21 @@ export const AccountPage: React.FC = () => {
455484
const tabs = getTabs();
456485

457486
useEffect(() => {
458-
if (!active_sub_tab) return;
459-
const parentKey = getParentMenuKey(active_sub_tab);
460-
if (!parentKey) return;
487+
const parentKey = getParentMenuKey(
488+
active_sub_tab ? active_sub_tab : active_page,
489+
);
461490
setOpenKeys((prevOpenKeys) =>
462-
prevOpenKeys.length === 1 && prevOpenKeys[0] === parentKey
463-
? prevOpenKeys
464-
: [parentKey],
491+
parentKey == null
492+
? []
493+
: prevOpenKeys.length === 1 && prevOpenKeys[0] === parentKey
494+
? prevOpenKeys
495+
: [parentKey],
465496
);
466-
}, [active_sub_tab]);
497+
}, [active_page, active_sub_tab]);
467498

468499
useEffect(() => {
469-
if (active_page !== "preferences") {
470-
if (active_sub_tab) {
471-
redux.getActions("account").setState({ active_sub_tab: undefined });
472-
}
473-
setOpenKeys([]);
500+
if (active_page !== "preferences" && active_sub_tab) {
501+
redux.getActions("account").setState({ active_sub_tab: undefined });
474502
}
475503
}, [active_page, active_sub_tab]);
476504

@@ -510,6 +538,25 @@ export const AccountPage: React.FC = () => {
510538
children[subTab.key] = subTab.children;
511539
titles[subTab.key] = subTab.label; // Always store original full label
512540
}
541+
} else if (tab.key === "billing" && Array.isArray(tab.children)) {
542+
const subTabs = tab.children;
543+
tab.children = subTabs.map((subTab) => {
544+
const label = hidden ? (
545+
<span style={{ paddingLeft: "5px" }}>
546+
{subTab.label.props.children[0]}
547+
</span>
548+
) : (
549+
subTab.label
550+
);
551+
return {
552+
key: subTab.key,
553+
label,
554+
};
555+
});
556+
for (const subTab of subTabs) {
557+
children[subTab.key] = subTab.children;
558+
titles[subTab.key] = subTab.label;
559+
}
513560
} else if (tab.key === "settings" || tab.key === "profile") {
514561
// Handle settings and profile as top-level pages
515562
// Store original full label for renderTitle()

0 commit comments

Comments
 (0)