feat(frontend): add flags to user page

This commit is contained in:
sam 2024-09-29 20:24:47 +02:00
parent f539902711
commit dc18ab60d2
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
10 changed files with 68 additions and 5 deletions

View file

@ -21,3 +21,9 @@
@import "@fontsource/firago/400.css"; @import "@fontsource/firago/400.css";
@import "@fontsource/firago/400-italic.css"; @import "@fontsource/firago/400-italic.css";
@import "@fontsource/firago/700.css"; @import "@fontsource/firago/700.css";
.pride-flag {
height: 1.5rem;
max-width: 200px;
border-radius: 3px;
}

View file

@ -1,5 +1,5 @@
import { CustomPreference, FieldEntry, Pronoun } from "~/lib/api/user"; import { CustomPreference, FieldEntry, Pronoun } from "~/lib/api/user";
import StatusLine from "~/components/StatusLine"; import StatusLine from "~/components/profile/StatusLine";
export default function ProfileField({ export default function ProfileField({
name, name,

View file

@ -0,0 +1,28 @@
import type { PrideFlag } from "~/lib/api/user";
import { OverlayTrigger, Tooltip } from "react-bootstrap";
export default function ProfileFlag({ flag }: { flag: PrideFlag }) {
return (
<span className="mx-2 my-1">
<OverlayTrigger
key={flag.id}
placement="top"
overlay={
<Tooltip id={flag.id} aria-hidden={true}>
{flag.description ?? flag.name}
</Tooltip>
}
>
<span>
<img
className="pride-flag"
src={flag.image_url}
alt={flag.description ?? flag.name}
style={{ pointerEvents: "none" }}
/>
</span>
</OverlayTrigger>{" "}
{flag.name}
</span>
);
}

View file

@ -7,8 +7,8 @@ import {
Pronoun, Pronoun,
} from "~/lib/api/user"; } from "~/lib/api/user";
import classNames from "classnames"; import classNames from "classnames";
import StatusIcon from "~/components/StatusIcon"; import StatusIcon from "~/components/profile/StatusIcon";
import PronounLink from "~/components/PronounLink"; import PronounLink from "~/components/profile/PronounLink";
export default function StatusLine({ export default function StatusLine({
entry, entry,

View file

@ -0,0 +1,5 @@
import { PartialMember, PrideFlag } from "~/lib/api/user";
export type Member = PartialMember & {
flags: PrideFlag[];
};

View file

@ -13,6 +13,7 @@ export type User = PartialUser & {
names: FieldEntry[]; names: FieldEntry[];
pronouns: Pronoun[]; pronouns: Pronoun[];
fields: Field[]; fields: Field[];
flags: PrideFlag[];
}; };
export type UserWithMembers = User & { members: PartialMember[] }; export type UserWithMembers = User & { members: PartialMember[] };
@ -50,6 +51,13 @@ export type Field = {
entries: FieldEntry[]; entries: FieldEntry[];
}; };
export type PrideFlag = {
id: string;
image_url: string;
name: string;
description: string | null;
};
export type CustomPreference = { export type CustomPreference = {
icon: string; icon: string;
tooltip: string; tooltip: string;

View file

@ -6,12 +6,13 @@ import { loader as rootLoader } from "~/root";
import { Alert, Button, Pagination } from "react-bootstrap"; import { Alert, Button, Pagination } from "react-bootstrap";
import { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import { renderMarkdown } from "~/lib/markdown"; import { renderMarkdown } from "~/lib/markdown";
import ProfileLink from "~/components/ProfileLink"; import ProfileLink from "~/components/profile/ProfileLink";
import ProfileField from "~/components/ProfileField"; import ProfileField from "~/components/profile/ProfileField";
import { PersonPlusFill } from "react-bootstrap-icons"; import { PersonPlusFill } from "react-bootstrap-icons";
import { defaultAvatarUrl } from "~/lib/utils"; import { defaultAvatarUrl } from "~/lib/utils";
import MemberCard from "~/routes/$username/MemberCard"; import MemberCard from "~/routes/$username/MemberCard";
import { ReactNode } from "react"; import { ReactNode } from "react";
import ProfileFlag from "~/components/profile/ProfileFlag";
export const meta: MetaFunction<typeof loader> = ({ data }) => { export const meta: MetaFunction<typeof loader> = ({ data }) => {
const { user } = data!; const { user } = data!;
@ -92,6 +93,13 @@ export default function UserPage() {
height={200} height={200}
className="rounded-circle img-fluid" className="rounded-circle img-fluid"
/> />
{user.flags && user.bio && (
<div className="d-flex flex-wrap m-4">
{user.flags.map((f, i) => (
<ProfileFlag flag={f} key={i} />
))}
</div>
)}
</div> </div>
<div className="col-md"> <div className="col-md">
{user.display_name ? ( {user.display_name ? (
@ -146,6 +154,14 @@ export default function UserPage() {
))} ))}
</div> </div>
</div> </div>
{/* If a user or member has no bio, flags are displayed in a row below the other profile info, rather than just below the avatar */}
{user.flags && !user.bio && (
<div className="d-flex flex-wrap m-4">
{user.flags.map((f, i) => (
<ProfileFlag flag={f} key={i} />
))}
</div>
)}
{(members.length > 0 || isMeUser) && ( {(members.length > 0 || isMeUser) && (
<> <>
<hr /> <hr />