From 4732451040962995215c84cea27c19e279e1a8ca Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 25 Sep 2024 16:43:53 +0200 Subject: [PATCH] feat(frontend): show user profile fields --- Foxnouns.Frontend/app/app.scss | 17 ++++++- .../app/components/ProfileField.tsx | 25 ++++++++++ .../app/components/StatusLine.tsx | 15 ++++-- .../app/components/nav/BaseNavbar.tsx | 2 +- .../app/components/nav/Navbar.tsx | 15 ++---- Foxnouns.Frontend/app/root.tsx | 27 +++++----- .../app/routes/$username/route.tsx | 49 ++++++++++--------- 7 files changed, 95 insertions(+), 55 deletions(-) create mode 100644 Foxnouns.Frontend/app/components/ProfileField.tsx diff --git a/Foxnouns.Frontend/app/app.scss b/Foxnouns.Frontend/app/app.scss index 3d3b499..45a8ee5 100644 --- a/Foxnouns.Frontend/app/app.scss +++ b/Foxnouns.Frontend/app/app.scss @@ -1,6 +1,21 @@ @use "bootstrap/scss/bootstrap" with ( $color-mode-type: media-query, - $font-family-sans-serif: ("FiraGO", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"), + $font-family-sans-serif: ( + "FiraGO", + system-ui, + -apple-system, + "Segoe UI", + Roboto, + "Helvetica Neue", + "Noto Sans", + "Liberation Sans", + Arial, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + "Segoe UI Symbol", + "Noto Color Emoji", + ) ); @import "@fontsource/firago/400.css"; diff --git a/Foxnouns.Frontend/app/components/ProfileField.tsx b/Foxnouns.Frontend/app/components/ProfileField.tsx new file mode 100644 index 0000000..ed5577d --- /dev/null +++ b/Foxnouns.Frontend/app/components/ProfileField.tsx @@ -0,0 +1,25 @@ +import { CustomPreference, FieldEntry, Pronoun } from "~/lib/api/user"; +import StatusLine from "~/components/StatusLine"; + +export default function ProfileField({ + name, + entries, + preferences, +}: { + name: string; + entries: Array; + preferences: Record; +}) { + return ( +
+

{name}

+
    + {entries.map((e, i) => ( +
  • + +
  • + ))} +
+
+ ); +} diff --git a/Foxnouns.Frontend/app/components/StatusLine.tsx b/Foxnouns.Frontend/app/components/StatusLine.tsx index 39e0aa6..b39222f 100644 --- a/Foxnouns.Frontend/app/components/StatusLine.tsx +++ b/Foxnouns.Frontend/app/components/StatusLine.tsx @@ -8,15 +8,14 @@ import { import classNames from "classnames"; import { ReactNode } from "react"; import StatusIcon from "~/components/StatusIcon"; +import PronounLink from "~/components/PronounLink"; export default function StatusLine({ entry, preferences, - children, }: { entry: FieldEntry | Pronoun; preferences: Record; - children: ReactNode; }) { const mergedPrefs = Object.assign({}, defaultPreferences, preferences); const currentPref = @@ -28,9 +27,19 @@ export default function StatusLine({ "fs-6": currentPref.size == PreferenceSize.Small, }); + if ("display_text" in entry) { + const pronoun = entry as Pronoun; + return ( + + {" "} + + + ); + } + return ( - {children} + {entry.value} ); } diff --git a/Foxnouns.Frontend/app/components/nav/BaseNavbar.tsx b/Foxnouns.Frontend/app/components/nav/BaseNavbar.tsx index ec5b8f5..43970d9 100644 --- a/Foxnouns.Frontend/app/components/nav/BaseNavbar.tsx +++ b/Foxnouns.Frontend/app/components/nav/BaseNavbar.tsx @@ -3,7 +3,7 @@ import { Nav, Navbar } from "react-bootstrap"; import { Link } from "@remix-run/react"; import Logo from "~/components/nav/Logo"; -export default function BaseNavbar({ children }: { children?: ReactNode; }) { +export default function BaseNavbar({ children }: { children?: ReactNode }) { return ( diff --git a/Foxnouns.Frontend/app/components/nav/Navbar.tsx b/Foxnouns.Frontend/app/components/nav/Navbar.tsx index c35366f..60471b9 100644 --- a/Foxnouns.Frontend/app/components/nav/Navbar.tsx +++ b/Foxnouns.Frontend/app/components/nav/Navbar.tsx @@ -6,12 +6,7 @@ import { Nav, NavDropdown } from "react-bootstrap"; import { useTranslation } from "react-i18next"; import BaseNavbar from "~/components/nav/BaseNavbar"; -export default function MainNavbar({ - user, -}: { - meta: Meta; - user?: User; -}) { +export default function MainNavbar({ user }: { meta: Meta; user?: User }) { const fetcher = useFetcher(); const { t } = useTranslation(); @@ -35,10 +30,6 @@ export default function MainNavbar({ {t("navbar.log-in")} ); - - return ( - - {userMenu} - - ); + + return {userMenu}; } diff --git a/Foxnouns.Frontend/app/root.tsx b/Foxnouns.Frontend/app/root.tsx index 02ce497..eadd87c 100644 --- a/Foxnouns.Frontend/app/root.tsx +++ b/Foxnouns.Frontend/app/root.tsx @@ -75,21 +75,18 @@ export function Layout({ children }: { children: ReactNode }) { useChangeLanguage(locale || "en"); return ( - - - - - - - - - - {children} - - + + + + + + + + + + {children} + + ); diff --git a/Foxnouns.Frontend/app/routes/$username/route.tsx b/Foxnouns.Frontend/app/routes/$username/route.tsx index b8ff310..6a40dad 100644 --- a/Foxnouns.Frontend/app/routes/$username/route.tsx +++ b/Foxnouns.Frontend/app/routes/$username/route.tsx @@ -7,8 +7,7 @@ import { Alert } from "react-bootstrap"; import { Trans, useTranslation } from "react-i18next"; import { renderMarkdown } from "~/lib/markdown"; import ProfileLink from "~/components/ProfileLink"; -import StatusLine from "~/components/StatusLine"; -import PronounLink from "~/components/PronounLink"; +import ProfileField from "~/components/ProfileField"; export const meta: MetaFunction = ({ data }) => { const { user } = data!; @@ -18,17 +17,21 @@ export const meta: MetaFunction = ({ data }) => { export const loader = async ({ request, params }: LoaderFunctionArgs) => { const url = new URL(request.url); - const memberPage = parseInt(url.searchParams.get("page") ?? "0", 10); + let memberPage = parseInt(url.searchParams.get("page") ?? "0", 10); let username = params.username!; if (!username.startsWith("@")) throw redirect(`/@${username}`); username = username.substring("@".length); const user = await serverRequest("GET", `/users/${username}`); + const pageCount = Math.ceil(user.members.length / 20); let members = user.members.slice(memberPage * 20, (memberPage + 1) * 20); - if (members.length === 0) members = user.members.slice(0, 20); + if (members.length === 0) { + members = user.members.slice(0, 20); + memberPage = 0; + } - return json({ user, members }); + return json({ user, members, currentPage: memberPage, pageCount }); }; export default function UserPage() { @@ -90,27 +93,27 @@ export default function UserPage() {
{user.names.length > 0 && ( -
-

{t("user.heading.names")}

-
    - {user.names.map((n, i) => ( - - {n.value} - - ))} -
-
+ )} {user.pronouns.length > 0 && ( -
-

{t("user.heading.pronouns")}

- {user.pronouns.map((p, i) => ( - - - - ))} -
+ )} + {user.fields.map((f, i) => ( + + ))}