Skip to content

Commit 51c0cd6

Browse files
committed
[dashboard] Improve usage-based billing account selection UX
1 parent abafff5 commit 51c0cd6

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

components/dashboard/src/components/BillingAccountSelector.tsx

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import { useContext, useEffect, useState } from "react";
8-
import { Team } from "@gitpod/gitpod-protocol";
8+
import { Team, TeamMemberInfo } from "@gitpod/gitpod-protocol";
99
import { AttributionId } from "@gitpod/gitpod-protocol/lib/attribution";
1010
import { getGitpodService } from "../service/service";
1111
import { TeamsContext } from "../teams/teams-context";
@@ -17,6 +17,7 @@ export function BillingAccountSelector(props: { onSelected?: () => void }) {
1717
const { user, setUser } = useContext(UserContext);
1818
const { teams } = useContext(TeamsContext);
1919
const [teamsWithBillingEnabled, setTeamsWithBillingEnabled] = useState<Team[] | undefined>();
20+
const [membersByTeam, setMembersByTeam] = useState<Record<string, TeamMemberInfo[]>>({});
2021

2122
useEffect(() => {
2223
if (!teams) {
@@ -31,9 +32,28 @@ export function BillingAccountSelector(props: { onSelected?: () => void }) {
3132
teamsWithBilling.push(t);
3233
}
3334
}),
34-
).then(() => setTeamsWithBillingEnabled(teamsWithBilling));
35+
).then(() => setTeamsWithBillingEnabled(teamsWithBilling.sort((a, b) => (a.name > b.name ? 1 : -1))));
3536
}, [teams]);
3637

38+
useEffect(() => {
39+
if (!teamsWithBillingEnabled) {
40+
return;
41+
}
42+
(async () => {
43+
const members: Record<string, TeamMemberInfo[]> = {};
44+
await Promise.all(
45+
teamsWithBillingEnabled.map(async (team) => {
46+
try {
47+
members[team.id] = await getGitpodService().server.getTeamMembers(team.id);
48+
} catch (error) {
49+
console.error("Could not get members of team", team, error);
50+
}
51+
}),
52+
);
53+
setMembersByTeam(members);
54+
})();
55+
}, [teamsWithBillingEnabled]);
56+
3757
const setUsageAttributionTeam = async (team?: Team) => {
3858
if (!user) {
3959
return;
@@ -63,15 +83,17 @@ export function BillingAccountSelector(props: { onSelected?: () => void }) {
6383
<p>Bill all my usage to:</p>
6484
<div className="mt-4 flex space-x-3">
6585
{/* <SelectableCardSolid
66-
className="w-36 h-32"
86+
className="w-60 h-18"
6787
title="(myself)"
6888
selected={
6989
!!user &&
7090
selectedAttributionId === AttributionId.render({ kind: "user", userId: user.id })
7191
}
7292
onClick={() => setUsageAttributionTeam(undefined)}
7393
>
74-
<div className="flex-grow flex items-end p-1"></div>
94+
<div className="flex-grow flex items-end px-1">
95+
<span className="text-sm text-gray-400">Personal Account</span>
96+
</div>
7597
</SelectableCardSolid> */}
7698
{teamsWithBillingEnabled.length === 0 && (
7799
<span>
@@ -81,14 +103,22 @@ export function BillingAccountSelector(props: { onSelected?: () => void }) {
81103
)}
82104
{teamsWithBillingEnabled.map((t) => (
83105
<SelectableCardSolid
84-
className="w-36 h-32"
106+
className="w-60 h-18"
85107
title={t.name}
86108
selected={
87109
selectedAttributionId === AttributionId.render({ kind: "team", teamId: t.id })
88110
}
89111
onClick={() => setUsageAttributionTeam(t)}
90112
>
91-
<div className="flex-grow flex items-end p-1"></div>
113+
<div className="flex-grow flex items-end px-1">
114+
<span className="text-sm text-gray-400">
115+
{!!membersByTeam[t.id]
116+
? `${membersByTeam[t.id].length} member${
117+
membersByTeam[t.id].length === 1 ? "" : "s"
118+
}`
119+
: "..."}
120+
</span>
121+
</div>
92122
</SelectableCardSolid>
93123
))}
94124
</div>

components/dashboard/src/settings/Billing.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import { BillingAccountSelector } from "../components/BillingAccountSelector";
1010
export default function Billing() {
1111
return (
1212
<PageWithSettingsSubMenu title="Billing" subtitle="Usage-Based Billing.">
13-
<h3>Usage-Based Billing</h3>
14-
<h2 className="text-gray-500">Manage usage-based billing, spending limit, and payment method.</h2>
1513
<div className="mt-8">
1614
<h3>Billing Account</h3>
1715
<BillingAccountSelector />

0 commit comments

Comments
 (0)