Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/dashboard/src/app/account/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default async function AccountLayout(props: {
children: React.ReactNode;
}) {
return (
<div className="flex min-h-full flex-col bg-background">
<div className="flex min-h-screen flex-col bg-background">
<div className="flex grow flex-col">
<HeaderAndNav />
<div className="border-border border-b py-10">
Expand Down
33 changes: 33 additions & 0 deletions apps/dashboard/src/app/account/settings/AccountSettingsPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use client";

import type { Account } from "@3rdweb-sdk/react/hooks/useApi";
import type { ThirdwebClient } from "thirdweb";
import { upload } from "thirdweb/storage";
import { AccountSettingsPageUI } from "./AccountSettingsPageUI";

export function AccountSettingsPage(props: {
account: Account;
client: ThirdwebClient;
}) {
return (
<AccountSettingsPageUI
account={props.account}
updateAccountImage={async (file) => {
if (file) {
// upload to IPFS
const ipfsUri = await upload({
client: props.client,
files: [file],
});

// TODO - Implement updating the account image with uri
console.log(ipfsUri);
} else {
// TODO - Implement deleting the account image
}

throw new Error("Not implemented");
}}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ function Variants() {
name: "John Doe",
email: "johndoe@gmail.com",
}}
updateAccountImage={async () => {
await new Promise((resolve) => setTimeout(resolve, 1000));
}}
/>
</div>
<Toaster richColors />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ type MinimalAccount = Pick<

export function AccountSettingsPageUI(props: {
account: MinimalAccount;
updateAccountImage: (file: File | undefined) => Promise<void>;
}) {
return (
<div className="flex flex-col gap-8">
<AccountAvatarFormControl />
<AccountAvatarFormControl updateAccountImage={props.updateAccountImage} />
<AccountNameFormControl name={props.account.name || ""} />
<AccountEmailFormControl
email={props.account.email || ""}
Expand All @@ -58,16 +59,14 @@ export function AccountSettingsPageUI(props: {
);
}

function AccountAvatarFormControl() {
function AccountAvatarFormControl(props: {
updateAccountImage: (file: File | undefined) => Promise<void>;
}) {
const [avatar, setAvatar] = useState<File>(); // TODO: prefill with account avatar

// TODO - implement
const updateAvatarMutation = useMutation({
mutationFn: async (_avatar: File | undefined) => {
// Fake loading
await new Promise((resolve) => setTimeout(resolve, 3000));
console.log("Updating account image to", _avatar);
throw new Error("Not implemented");
await props.updateAccountImage(_avatar);
},
});

Expand Down
11 changes: 8 additions & 3 deletions apps/dashboard/src/app/account/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { getThirdwebClient } from "@/constants/thirdweb.server";
import { redirect } from "next/navigation";
import { AccountSettingsPageUI } from "./AccountSettingsPageUI";
import { getAuthToken } from "../../api/lib/getAuthToken";
import { AccountSettingsPage } from "./AccountSettingsPage";
import { getAccount } from "./getAccount";

export default async function Page() {
const account = await getAccount();
const token = getAuthToken();

if (!account) {
if (!account || !token) {
redirect(`/login?next=${encodeURIComponent("/account")}`);
}

return <AccountSettingsPageUI account={account} />;
return (
<AccountSettingsPage account={account} client={getThirdwebClient(token)} />
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import type { Meta, StoryObj } from "@storybook/react";
import { mobileViewport } from "../../../../../../../stories/utils";
import {
DeleteTeamCard,
GeneralSettingsPage,
LeaveTeamCard,
} from "./GeneralSettingsPage";
TeamGeneralSettingsPageUI,
} from "./TeamGeneralSettingsPageUI";

const meta = {
title: "Team/Settings/General",
Expand Down Expand Up @@ -47,7 +47,12 @@ const testTeam: Team = {
function Story() {
return (
<div className="mx-auto w-full max-w-[1100px] px-4 py-6">
<GeneralSettingsPage team={testTeam} />
<TeamGeneralSettingsPageUI
team={testTeam}
updateTeamImage={async () => {
await new Promise((resolve) => setTimeout(resolve, 1000));
}}
/>
<ComponentVariantions />
<Toaster richColors />
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use client";

import type { Team } from "@/api/team";
import type { ThirdwebClient } from "thirdweb";
import { upload } from "thirdweb/storage";
import { TeamGeneralSettingsPageUI } from "./TeamGeneralSettingsPageUI";

export function TeamGeneralSettingsPage(props: {
team: Team;
client: ThirdwebClient;
}) {
return (
<TeamGeneralSettingsPageUI
team={props.team}
updateTeamImage={async (file) => {
if (file) {
// upload to IPFS
const uri = await upload({
client: props.client,
files: [file],
});

// TODO - Implement updating the account image with uri
console.log(uri);
} else {
// TODO - Implement deleting the account image
}

throw new Error("Not implemented");
}}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ import { FileInput } from "components/shared/FileInput";
import { useState } from "react";
import { toast } from "sonner";

export function GeneralSettingsPage(props: {
export function TeamGeneralSettingsPageUI(props: {
team: Team;
updateTeamImage: (file: File | undefined) => Promise<void>;
}) {
const hasPermissionToDelete = false; // TODO
return (
<div className="flex flex-col gap-8">
<TeamNameFormControl team={props.team} />
<TeamSlugFormControl team={props.team} />
<TeamAvatarFormControl />
<TeamAvatarFormControl updateTeamImage={props.updateTeamImage} />
<TeamIdCard team={props.team} />
<LeaveTeamCard enabled={false} teamName={props.team.name} />
<DeleteTeamCard
Expand Down Expand Up @@ -141,16 +142,14 @@ function TeamSlugFormControl(props: {
);
}

function TeamAvatarFormControl() {
function TeamAvatarFormControl(props: {
updateTeamImage: (file: File | undefined) => Promise<void>;
}) {
const [teamAvatar, setTeamAvatar] = useState<File>(); // TODO: prefill with team avatar

// TODO - implement
const updateTeamAvatarMutation = useMutation({
mutationFn: async (_avatar: File | undefined) => {
// Fake loading
await new Promise((resolve) => setTimeout(resolve, 3000));
console.log("Updating team name to", _avatar);
throw new Error("Not implemented");
await props.updateTeamImage(_avatar);
},
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import { getTeamBySlug } from "@/api/team";
import { getThirdwebClient } from "@/constants/thirdweb.server";
import { notFound } from "next/navigation";
import { GeneralSettingsPage } from "./general/GeneralSettingsPage";
import { getAuthToken } from "../../../../../api/lib/getAuthToken";
import { TeamGeneralSettingsPage } from "./general/TeamGeneralSettingsPage";

export default async function Page(props: {
params: {
team_slug: string;
};
}) {
const team = await getTeamBySlug(props.params.team_slug);

if (!team) {
const token = getAuthToken();
if (!team || !token) {
notFound();
}

return <GeneralSettingsPage team={team} />;
return (
<TeamGeneralSettingsPage team={team} client={getThirdwebClient(token)} />
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export function ProjectGeneralSettingsPageForTeams(props: {
const { team_slug, project_slug, apiKey } = props;
const projectSettingsLayout = `/team/${team_slug}/${project_slug}/settings`;

// TODO - add a Project Image form field on this page

return (
<ProjectGeneralSettingsPage
apiKey={apiKey}
Expand Down