From ba24815320eec75a8a58121cf5c22b0c419a1e0c Mon Sep 17 00:00:00 2001 From: hanabi Date: Thu, 24 Nov 2022 14:44:47 -0500 Subject: [PATCH] refactor(frontend): some degree of api wrapping --- frontend/components/Navigation.tsx | 3 +- frontend/components/PersonPage.tsx | 229 +++++++++--------------- frontend/lib/{types.ts => api-fetch.ts} | 63 +++++-- frontend/lib/api.ts | 209 +++++++++++++++++++++ frontend/lib/fetch.ts | 32 ---- frontend/lib/state.ts | 2 +- frontend/pages/edit/profile.tsx | 5 +- frontend/pages/login/discord.tsx | 3 +- frontend/pages/login/index.tsx | 2 +- frontend/pages/u/[user]/[member].tsx | 24 +-- frontend/pages/u/[user]/index.tsx | 15 +- 11 files changed, 365 insertions(+), 222 deletions(-) rename frontend/lib/{types.ts => api-fetch.ts} (56%) create mode 100644 frontend/lib/api.ts delete mode 100644 frontend/lib/fetch.ts diff --git a/frontend/components/Navigation.tsx b/frontend/components/Navigation.tsx index 2d9d1fe..22930c9 100644 --- a/frontend/components/Navigation.tsx +++ b/frontend/components/Navigation.tsx @@ -6,8 +6,7 @@ import NavItem from "./NavItem"; import Logo from "./logo"; import { useRecoilState } from "recoil"; import { userState } from "../lib/state"; -import fetchAPI from "../lib/fetch"; -import { APIError, ErrorCode, MeUser } from "../lib/types"; +import { fetchAPI, APIError, ErrorCode, MeUser } from "../lib/api-fetch"; export default function Navigation() { const [user, setUser] = useRecoilState(userState); diff --git a/frontend/components/PersonPage.tsx b/frontend/components/PersonPage.tsx index ed13e74..5484885 100644 --- a/frontend/components/PersonPage.tsx +++ b/frontend/components/PersonPage.tsx @@ -1,14 +1,4 @@ import Head from "next/head"; -import { - Field, - Member, - Name, - PartialPerson, - Person, - Pronoun, - User, - WordStatus, -} from "../lib/types"; import ReactMarkdown from "react-markdown"; import { userState } from "../lib/state"; import { useRecoilValue } from "recoil"; @@ -23,12 +13,13 @@ import { import BlueLink from "./BlueLink"; import React from "react"; import Card from "./Card"; +import { Field, Label, LabelStatus, Person, User } from "../lib/api"; export default function PersonPage({ person }: { person: Person }) { return ( <> - {`${personFullHandle(person)} - pronouns.cc`} + {`${person.fullHandle()} - pronouns.cc`} @@ -47,97 +38,42 @@ export default function PersonPage({ person }: { person: Person }) { - - - - {"user" in person ? ( - {`< ${ - person.user.display_name ?? person.user.name - }`} + + + + {person instanceof User ? ( + ) : ( - + {`< ${person.display()}`} )} ); } -/** Full handle of a person. */ -function personFullHandle(person: Person) { - return "user" in person - ? `&${person.name}@${person.user.name}` - : `@${person.name}`; -} - -/** Short handle of a person. */ -function personShortHandle(person: Person) { - return ("user" in person ? "&" : "@") + person.name; -} - -/** The user (account) associated with a person. */ -function personUser(person: Person) { - return "user" in person ? person.user : person; -} - -/** The (relative) URL pointing to a person. */ -function personURL(person: PartialPerson | Member) { - const domain = - typeof window !== "undefined" ? window.location.origin : process.env.DOMAIN; - return `${domain}/u/${"user" in person ? `${person.user.name}/` : ""}${ - person.name - }`; -} - function PersonHead({ person }: { person: Person }) { - const { - id, - name, - display_name, - avatar_urls, - bio, - links, - names, - pronouns, - fields, - } = person; + const { displayName, avatarUrls, bio, names, pronouns } = person; let description = ""; - if ( - names?.filter((name) => name.status === WordStatus.Favourite)?.length && - pronouns?.filter((pronoun) => pronoun.status === WordStatus.Favourite) - ?.length - ) { - description = `${personShortHandle(person)} goes by ${names - .filter((name) => name.status === WordStatus.Favourite) - .map((name) => name.name) - .join(", ")} and uses ${pronouns - .filter((pronoun) => pronoun.status === WordStatus.Favourite) - .map( - (pronoun) => - pronoun.display_text ?? - pronoun.pronouns.split("/").slice(0, 2).join("/") - ) - .join(", ")} pronouns.`; - } else if ( - names?.filter((name) => name.status === WordStatus.Favourite)?.length - ) { - description = `${personShortHandle(person)} goes by ${names - .filter((name) => name.status === WordStatus.Favourite) - .map((name) => name.name) - .join(", ")}.`; - } else if ( - pronouns?.filter((pronoun) => pronoun.status === WordStatus.Favourite) - ?.length - ) { - description = `${personShortHandle(person)} uses ${pronouns - .filter((pronoun) => pronoun.status === WordStatus.Favourite) - .map( - (pronoun) => - pronoun.display_text ?? - pronoun.pronouns.split("/").slice(0, 2).join("/") - ) - .join(", ")} pronouns.`; + const favNames = names.filter((x) => x.status === LabelStatus.Favourite); + const favPronouns = pronouns.filter( + (x) => x.status === LabelStatus.Favourite + ); + if (favNames.length || favPronouns.length) { + description = `${person.shortHandle()}${ + favNames.length + ? ` goes by ${favNames.map((x) => x.display()).join(", ")}` + : "" + }${favNames.length && favPronouns.length ? " and" : ""}${ + favPronouns.length + ? `uses ${favPronouns + .map((x) => x.shortDisplay()) + .join(", ")} pronouns.` + : "" + }`; } else if (bio && bio !== "") { - description = bio.slice(0, 500); + description = `${bio.slice(0, 500)}${bio.length > 500 ? "…" : ""}`; } return ( @@ -147,22 +83,20 @@ function PersonHead({ person }: { person: Person }) { key="og:title" property="og:title" content={ - display_name - ? `${display_name} (${personFullHandle(person)})` - : personFullHandle(person) + displayName + ? `${displayName} (${person.fullHandle()})` + : person.fullHandle() } /> - {avatar_urls && avatar_urls.length > 0 ? ( - - ) : ( - <> + {avatarUrls && avatarUrls.length > 0 && ( + )} - + ); } @@ -180,15 +114,15 @@ function IsOwnUserPageNotice({ person }: { person: Person }) { } function MemberList({ user, className }: { user: User; className?: string }) { - const partialMembers = user.members; + const partialMembers = user.partialMembers; return (

Members