/** * Renders a profile's description, which the signed-in user edits in place on * their own profile. * * @module */ import { t } from "@lingui/core/macro"; import { Trans } from "@lingui/react/macro"; import { API_URL } from "../../config/api.ts"; import { VALIDATION } from "../../../shared/validation.ts"; import type { Wire } from "../../../shared/api.ts"; import type { PublicUser, UpdateUserRequest } from "../../../shared/user.ts"; import { expectOk } from "../../utils/shared/api.ts"; import { useAuth } from "../../hooks/auth/useAuth.ts"; import { InlineEdit } from "../form/InlineEdit.tsx"; import { Markdown } from "../editor/Markdown.tsx"; /** Passed to {@link ProfileDescription} by `UserPublicProfile`. */ export interface ProfileDescriptionProps { description: string | undefined; isOwnProfile: boolean; /** Called with the saved description, undefined once cleared. */ onSaved: (description: string | undefined) => void; } /** * Renders the description in Markdown, or nothing when there is none. On * their own profile, users get a "Who am I?" placeholder instead, and edit it * in place, saved to `PATCH /api/me`. Other browsers see the change through * the socket's `user_updated` event. */ export function ProfileDescription( { description, isOwnProfile, onSaved }: ProfileDescriptionProps, ): React.JSX.Element | null { const { authFetch } = useAuth(); if (!description && !isOwnProfile) return null; return (
{ // Sent even when empty, since the server keeps the old one when it // is left out. await expectOk>( await authFetch(`${API_URL}/api/me`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify( { description: saved } satisfies UpdateUserRequest, ), }), ); onSaved(saved || undefined); }} kind="markdown" maxLength={VALIDATION.USER_DESCRIPTION_MAX} placeholder={t`Who am I?`} > {description ? ( {description} ) : (

Who am I?

)}
); }