Skip to content

Commit 82f54ef

Browse files
committed
Plug in Team settings page UI to API
1 parent 025c581 commit 82f54ef

File tree

7 files changed

+92
-44
lines changed

7 files changed

+92
-44
lines changed

apps/dashboard/src/@/api/team.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ export type Team = {
99
slug: string;
1010
createdAt: string;
1111
updatedAt: string;
12-
deletedAt: string | null;
13-
bannedAt: string | null;
14-
// image: string; // -> TODO
12+
deletedAt?: string;
13+
bannedAt?: string;
14+
image?: string;
1515
billingPlan: "pro" | "growth" | "free";
1616
billingStatus: "validPayment" | (string & {}); // what's the other value?
17-
// billingEmail: string;
17+
billingEmail: string;
1818
// billingExternalId: string;
1919
// billingType: "STRIPE" | ??
2020
// billingCustomerPayload: ?? | null

apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/GeneralSettingsPage.stories.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@ const testTeam: Team = {
3838
slug: "team-slug-foo-bar",
3939
createdAt: "2023-07-07T19:21:33.604Z",
4040
updatedAt: "2024-07-11T00:01:02.241Z",
41-
deletedAt: null,
42-
bannedAt: null,
4341
billingStatus: "validPayment",
4442
billingPlan: "free",
43+
billingEmail: "[email protected]",
4544
};
4645

4746
function Story() {
@@ -52,6 +51,10 @@ function Story() {
5251
updateTeamImage={async () => {
5352
await new Promise((resolve) => setTimeout(resolve, 1000));
5453
}}
54+
updateTeamField={async (value) => {
55+
console.log(value);
56+
await new Promise((resolve) => setTimeout(resolve, 1000));
57+
}}
5558
/>
5659
<ComponentVariantions />
5760
<Toaster richColors />
Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,79 @@
11
"use client";
22

33
import type { Team } from "@/api/team";
4-
import type { ThirdwebClient } from "thirdweb";
4+
import { API_SERVER_URL } from "@/constants/env";
5+
import { getThirdwebClient } from "@/constants/thirdweb.server";
6+
import { useDashboardRouter } from "@/lib/DashboardRouter";
57
import { upload } from "thirdweb/storage";
68
import { TeamGeneralSettingsPageUI } from "./TeamGeneralSettingsPageUI";
79

810
export function TeamGeneralSettingsPage(props: {
911
team: Team;
10-
client: ThirdwebClient;
12+
authToken: string;
1113
}) {
14+
const router = useDashboardRouter();
15+
1216
return (
1317
<TeamGeneralSettingsPageUI
1418
team={props.team}
19+
updateTeamField={async (teamValue) => {
20+
const res = await updateTeam({
21+
teamId: props.team.id,
22+
value: teamValue,
23+
authToken: props.authToken,
24+
});
25+
26+
// Current page's slug is updated
27+
if (teamValue.slug) {
28+
router.replace(`/team/${teamValue.slug}/~/settings`);
29+
} else {
30+
router.refresh();
31+
}
32+
33+
if (!res.ok) {
34+
console.error(res);
35+
throw new Error("Failed to update team name");
36+
}
37+
}}
1538
updateTeamImage={async (file) => {
39+
let uri: string | undefined = undefined;
40+
1641
if (file) {
1742
// upload to IPFS
18-
const uri = await upload({
19-
client: props.client,
43+
uri = await upload({
44+
client: getThirdwebClient(props.authToken),
2045
files: [file],
2146
});
22-
23-
// TODO - Implement updating the account image with uri
24-
console.log(uri);
25-
} else {
26-
// TODO - Implement deleting the account image
2747
}
2848

29-
throw new Error("Not implemented");
49+
const res = await updateTeam({
50+
teamId: props.team.id,
51+
value: {
52+
image: uri,
53+
},
54+
authToken: props.authToken,
55+
});
56+
57+
if (!res.ok) {
58+
console.error(res);
59+
throw new Error("Failed to update team image");
60+
}
3061
}}
3162
/>
3263
);
3364
}
65+
66+
function updateTeam(params: {
67+
teamId: string;
68+
value: Partial<Team>;
69+
authToken: string;
70+
}) {
71+
return fetch(`${API_SERVER_URL}/v1/teams/${params.teamId}`, {
72+
method: "PUT",
73+
headers: {
74+
"Content-Type": "application/json",
75+
Authorization: `Bearer ${params.authToken}`,
76+
},
77+
body: JSON.stringify(params.value),
78+
});
79+
}

apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/TeamGeneralSettingsPageUI.tsx

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,28 @@ import { FileInput } from "components/shared/FileInput";
1111
import { useState } from "react";
1212
import { toast } from "sonner";
1313

14+
type UpdateTeamField = (team: Partial<Team>) => Promise<void>;
15+
1416
export function TeamGeneralSettingsPageUI(props: {
1517
team: Team;
1618
updateTeamImage: (file: File | undefined) => Promise<void>;
19+
updateTeamField: UpdateTeamField;
1720
}) {
1821
const hasPermissionToDelete = false; // TODO
1922
return (
2023
<div className="flex flex-col gap-8">
21-
<TeamNameFormControl team={props.team} />
22-
<TeamSlugFormControl team={props.team} />
23-
<TeamAvatarFormControl updateTeamImage={props.updateTeamImage} />
24+
<TeamNameFormControl
25+
team={props.team}
26+
updateTeamField={props.updateTeamField}
27+
/>
28+
<TeamSlugFormControl
29+
team={props.team}
30+
updateTeamField={props.updateTeamField}
31+
/>
32+
<TeamAvatarFormControl
33+
updateTeamImage={props.updateTeamImage}
34+
team={props.team}
35+
/>
2436
<TeamIdCard team={props.team} />
2537
<LeaveTeamCard enabled={false} teamName={props.team.name} />
2638
<DeleteTeamCard
@@ -33,17 +45,13 @@ export function TeamGeneralSettingsPageUI(props: {
3345

3446
function TeamNameFormControl(props: {
3547
team: Team;
48+
updateTeamField: UpdateTeamField;
3649
}) {
3750
const [teamName, setTeamName] = useState(props.team.name);
3851
const maxTeamNameLength = 32;
3952

40-
// TODO - implement
4153
const updateTeamMutation = useMutation({
42-
mutationFn: async (teamName: string) => {
43-
await new Promise((resolve) => setTimeout(resolve, 3000));
44-
console.log("Updating team name to", teamName);
45-
throw new Error("Not implemented");
46-
},
54+
mutationFn: (name: string) => props.updateTeamField({ name }),
4755
});
4856

4957
function handleSave() {
@@ -82,20 +90,14 @@ function TeamNameFormControl(props: {
8290

8391
function TeamSlugFormControl(props: {
8492
team: Team;
93+
updateTeamField: (team: Partial<Team>) => Promise<void>;
8594
}) {
8695
const [teamSlug, setTeamSlug] = useState(props.team.slug);
8796
const [isTeamTaken] = useState(false);
8897
const maxTeamURLLength = 48;
8998

90-
// TODO - implement
9199
const updateTeamMutation = useMutation({
92-
mutationFn: async (_slug: string) => {
93-
// set isTeamTaken to true if team URL is taken
94-
// Fake loading
95-
await new Promise((resolve) => setTimeout(resolve, 3000));
96-
console.log("Updating team slug to", _slug);
97-
throw new Error("Not implemented");
98-
},
100+
mutationFn: (slug: string) => props.updateTeamField({ slug: slug }),
99101
});
100102

101103
function handleSave() {
@@ -144,8 +146,11 @@ function TeamSlugFormControl(props: {
144146

145147
function TeamAvatarFormControl(props: {
146148
updateTeamImage: (file: File | undefined) => Promise<void>;
149+
team: Team;
147150
}) {
148-
const [teamAvatar, setTeamAvatar] = useState<File>(); // TODO: prefill with team avatar
151+
const [teamAvatar, setTeamAvatar] = useState<File | undefined>(
152+
props.team.image ? new File([props.team.image], "team-avatar") : undefined,
153+
);
149154

150155
const updateTeamAvatarMutation = useMutation({
151156
mutationFn: async (_avatar: File | undefined) => {

apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/members/TeamMembersSettingsPage.stories.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,9 @@ const freeTeam: Team = {
4040
slug: "team-slug-foo-bar",
4141
createdAt: "2023-07-07T19:21:33.604Z",
4242
updatedAt: "2024-07-11T00:01:02.241Z",
43-
deletedAt: null,
44-
bannedAt: null,
4543
billingStatus: "validPayment",
4644
billingPlan: "free",
45+
billingEmail: "[email protected]",
4746
};
4847

4948
const proTeam: Team = {
@@ -52,10 +51,9 @@ const proTeam: Team = {
5251
slug: "team-slug-foo-bar",
5352
createdAt: "2023-07-07T19:21:33.604Z",
5453
updatedAt: "2024-07-11T00:01:02.241Z",
55-
deletedAt: null,
56-
bannedAt: null,
5754
billingStatus: "validPayment",
5855
billingPlan: "pro",
56+
billingEmail: "[email protected]",
5957
};
6058

6159
function createMemberStub(id: string, role: TeamAccountRole): TeamMember {

apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/page.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { getTeamBySlug } from "@/api/team";
2-
import { getThirdwebClient } from "@/constants/thirdweb.server";
32
import { notFound } from "next/navigation";
43
import { getAuthToken } from "../../../../../api/lib/getAuthToken";
54
import { TeamGeneralSettingsPage } from "./general/TeamGeneralSettingsPage";
@@ -15,7 +14,5 @@ export default async function Page(props: {
1514
notFound();
1615
}
1716

18-
return (
19-
<TeamGeneralSettingsPage team={team} client={getThirdwebClient(token)} />
20-
);
17+
return <TeamGeneralSettingsPage team={team} authToken={token} />;
2118
}

apps/dashboard/src/stories/stubs.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,9 @@ export function teamStub(
4545
billingStatus: "validPayment",
4646
name: `Team ${id}`,
4747
slug: `team-${id}`,
48-
bannedAt: null,
4948
createdAt: new Date().toISOString(),
50-
deletedAt: null,
5149
updatedAt: new Date().toISOString(),
50+
billingEmail: "[email protected]",
5251
};
5352

5453
return team;

0 commit comments

Comments
 (0)