From e5b4f7899821334a03441f9dd0418f761855691c Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 20 Nov 2022 16:54:25 +0100 Subject: [PATCH] feat(frontend): add new field, new field entry, save buttons to edit profile page --- frontend/components/Button.tsx | 13 +++- frontend/components/Editable.tsx | 26 +++++++- frontend/components/TextInput.tsx | 2 + frontend/pages/edit/profile.tsx | 98 ++++++++++++++++++++++++++----- 4 files changed, 120 insertions(+), 19 deletions(-) diff --git a/frontend/components/Button.tsx b/frontend/components/Button.tsx index d61c84c..74cb7c6 100644 --- a/frontend/components/Button.tsx +++ b/frontend/components/Button.tsx @@ -10,6 +10,7 @@ export interface Props { onClick?: MouseEventHandler; style?: ButtonStyle; bold?: boolean; + noRound?: boolean; children?: ReactNode; } @@ -33,7 +34,9 @@ function PrimaryButton(props: Props) { @@ -45,7 +48,9 @@ function SuccessButton(props: Props) { @@ -57,7 +62,9 @@ function DangerButton(props: Props) { diff --git a/frontend/components/Editable.tsx b/frontend/components/Editable.tsx index c796b12..2de0434 100644 --- a/frontend/components/Editable.tsx +++ b/frontend/components/Editable.tsx @@ -4,12 +4,14 @@ import { HandThumbsUp, Heart, People, + Plus, Trash3, } from "react-bootstrap-icons"; import Card from "./Card"; import TextInput from "./TextInput"; import Button, { ButtonStyle } from "./Button"; +import { useState } from "react"; export interface EditField { id: number; @@ -28,6 +30,8 @@ export enum PronounChoice { type EditableCardProps = { field: EditField; onChangeName: React.ChangeEventHandler; + onChangePronoun: React.ChangeEventHandler; + onAddPronoun(pronoun: string): void; onChangeFavourite( e: React.MouseEvent, entry: string @@ -40,6 +44,8 @@ type EditableCardProps = { }; export function EditableCard(props: EditableCardProps) { + const [input, setInput] = useState(""); + const footer = (
@@ -55,8 +61,12 @@ export function EditableCard(props: EditableCardProps) { {Object.keys(props.field.pronouns).map((pronoun, index) => { const choice = props.field.pronouns[pronoun]; return ( -
  • -
    {pronoun}
    +
  • +
    +
  • ); diff --git a/frontend/components/TextInput.tsx b/frontend/components/TextInput.tsx index a2b8ba8..8cf7357 100644 --- a/frontend/components/TextInput.tsx +++ b/frontend/components/TextInput.tsx @@ -2,6 +2,7 @@ import { ChangeEventHandler } from "react"; export type Props = { contrastBackground?: boolean; + prevValue?: string; defaultValue?: string; value?: string; onChange?: ChangeEventHandler; @@ -15,6 +16,7 @@ export default function TextInput(props: Props) { return ( { + setFields(cloneDeep(originalOrder)); + }; + const addField = () => { + if (fields.length >= 25) return; + + const lastId = fields[fields.length - 1]?.id ?? 0; + + setFields([...fields, { id: lastId + 1, name: "", pronouns: {} }]); + }; useEffect(() => { if (!user) { @@ -61,11 +73,53 @@ export default function Index() { } const fieldsUpdated = !fieldsEqual(fields, originalOrder); + const isEdited = fieldsUpdated; return (
    +

    + Editing your profile + {isEdited && ( + + )} +

    +
    {`fieldsUpdated: ${fieldsUpdated}`}
    - {/* @ts-ignore: This component isn't updated to have a "children" prop yet, but it accepts it just fine. */} +

    + Fields +
    + + {fieldsUpdated && ( + + )} +
    +

    { + const prev = + e.target.attributes.getNamedItem("data-prev-value")?.value; + if (!prev || !e.target.value) return; + + const choice = field.pronouns[prev]; + delete field.pronouns[prev]; + + field.pronouns[e.target.value] = choice; + + setFields([...fields]); + }} + onAddPronoun={(pronoun) => { + field.pronouns[pronoun] = PronounChoice.okay; + setFields([...fields]); + }} onChangeName={(e) => { field.name = e.target.value; setFields([...fields]); @@ -125,8 +195,8 @@ function fieldsEqual(arr1: EditField[], arr2: EditField[]) { } async function updateUser(args: { - displayName: string; - bio: string; + displayName: string | null; + bio: string | null; fields: EditField[]; }) { const newFields = args.fields.map((editField) => { @@ -139,22 +209,22 @@ async function updateUser(args: { avoid: [], }; - Object.keys(editField).forEach((pronoun) => { + Object.keys(editField.pronouns).forEach((pronoun) => { switch (editField.pronouns[pronoun]) { case PronounChoice.favourite: - field.favourite?.push(pronoun); + field.favourite!.push(pronoun); break; case PronounChoice.okay: - field.okay?.push(pronoun); + field.okay!.push(pronoun); break; case PronounChoice.jokingly: - field.jokingly?.push(pronoun); + field.jokingly!.push(pronoun); break; case PronounChoice.friendsOnly: - field.friends_only?.push(pronoun); + field.friends_only!.push(pronoun); break; case PronounChoice.avoid: - field.avoid?.push(pronoun); + field.avoid!.push(pronoun); break; } }); @@ -163,8 +233,8 @@ async function updateUser(args: { }); return await fetchAPI("/users/@me", "PATCH", { - display_name: args.displayName, - bio: args.bio, + display_name: args.displayName ?? null, + bio: args.bio ?? null, fields: newFields, }); }