feat(frontend): add flags to user page
This commit is contained in:
parent
f539902711
commit
dc18ab60d2
10 changed files with 68 additions and 5 deletions
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
28
Foxnouns.Frontend/app/components/profile/ProfileFlag.tsx
Normal file
28
Foxnouns.Frontend/app/components/profile/ProfileFlag.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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,
|
5
Foxnouns.Frontend/app/lib/api/member.ts
Normal file
5
Foxnouns.Frontend/app/lib/api/member.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { PartialMember, PrideFlag } from "~/lib/api/user";
|
||||||
|
|
||||||
|
export type Member = PartialMember & {
|
||||||
|
flags: PrideFlag[];
|
||||||
|
};
|
|
@ -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;
|
||||||
|
|
|
@ -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 />
|
||||||
|
|
Loading…
Reference in a new issue