Files
gerbeur/src/components/profile/ProfileManageTab.tsx

78 lines
2.5 KiB
TypeScript

/**
* Renders a profile's "manage" tab, `/@name/manage`, where those who hold
* `user:manage` change another user's role and name. The site's own tools are
* the `/manage` page's.
*
* @module
*/
import { Trans } from "@lingui/react/macro";
import { userApiUrl } from "../../utils/shared/urls.ts";
import type { Wire } from "../../../shared/api.ts";
import type { PublicUser } from "../../../shared/user.ts";
import { expectOk } from "../../utils/shared/api.ts";
import { deserializePublicUser } from "../../utils/shared/deserialize.ts";
import { useAuth } from "../../hooks/auth/useAuth.ts";
import { homeHost } from "../../utils/auth/home.ts";
import { ProfileSection } from "./ProfileSection.tsx";
import { RoleSwitcher } from "./RoleSwitcher.tsx";
import { SettingRow } from "./SettingRow.tsx";
import { UsernameField } from "./UsernameField.tsx";
/**
* Passed to {@link ProfileManageTab} by `UserPublicProfile`, which shows the
* tab on another user's profile to those who hold `user:manage`.
*/
export interface ProfileManageTabProps {
user: PublicUser;
/** Called with the user as the server left them. */
onUserSaved: (user: PublicUser) => void;
}
/**
* Renders the user's role and name. A rename here has no rate limit, and the
* profile's URL then takes the new name. A user from another instance is
* named there, so their name is only shown.
*/
export function ProfileManageTab(
{ user, onUserSaved }: ProfileManageTabProps,
): React.JSX.Element {
const { authFetch } = useAuth();
async function rename(username: string): Promise<string> {
const renamed = deserializePublicUser(
await expectOk<Wire<PublicUser>>(
await authFetch(userApiUrl(user, "username"), {
method: "PATCH",
body: JSON.stringify({ username }),
}),
),
);
onUserSaved(renamed);
return renamed.username;
}
return (
<ProfileSection title={<Trans>User management</Trans>}>
<div className="profile-appearance-grid">
<RoleSwitcher
userId={user.id}
currentRole={user.role}
onSaved={(role) => onUserSaved({ ...user, role })}
/>
<SettingRow label={<Trans>Username</Trans>}>
{homeHost(user.username)
? <span className="profile-appearance-value">{user.username}</span>
: (
<UsernameField
key={user.username}
username={user.username}
save={rename}
/>
)}
</SettingRow>
</div>
</ProfileSection>
);
}