feat(frontend): support new fields

This commit is contained in:
Sam 2023-03-04 23:03:30 +01:00
parent b41ca0b753
commit 66a0830ef2
No known key found for this signature in database
GPG Key ID: B4EF20DDE721CAA1
2 changed files with 51 additions and 95 deletions

View File

@ -12,19 +12,12 @@ import Card from "./Card";
import TextInput from "./TextInput"; import TextInput from "./TextInput";
import Button, { ButtonStyle } from "./Button"; import Button, { ButtonStyle } from "./Button";
import { useState } from "react"; import { useState } from "react";
import { WordStatus } from "../lib/api-fetch";
export interface EditField { export interface EditField {
id: number; id: number;
name: string; name: string;
pronouns: Record<string, PronounChoice>; values: Array<{ value: string; status: WordStatus }>;
}
export enum PronounChoice {
favourite,
okay,
jokingly,
friendsOnly,
avoid,
} }
type EditableCardProps = { type EditableCardProps = {
@ -32,15 +25,15 @@ type EditableCardProps = {
onChangeName: React.ChangeEventHandler<HTMLInputElement>; onChangeName: React.ChangeEventHandler<HTMLInputElement>;
onChangePronoun: React.ChangeEventHandler<HTMLInputElement>; onChangePronoun: React.ChangeEventHandler<HTMLInputElement>;
onAddPronoun(pronoun: string): void; onAddPronoun(pronoun: string): void;
onDeletePronoun(e: React.MouseEvent<HTMLButtonElement>, entry: string): void; onDeletePronoun(e: React.MouseEvent<HTMLButtonElement>, index: number): void;
onChangeFavourite( onChangeFavourite(
e: React.MouseEvent<HTMLButtonElement>, e: React.MouseEvent<HTMLButtonElement>,
entry: string index: number
): void; ): void;
onChangeOkay(e: React.MouseEvent<HTMLButtonElement>, entry: string): void; onChangeOkay(e: React.MouseEvent<HTMLButtonElement>, index: number): void;
onChangeJokingly(e: React.MouseEvent<HTMLButtonElement>, entry: string): void; onChangeJokingly(e: React.MouseEvent<HTMLButtonElement>, index: number): void;
onChangeFriends(e: React.MouseEvent<HTMLButtonElement>, entry: string): void; onChangeFriends(e: React.MouseEvent<HTMLButtonElement>, index: number): void;
onChangeAvoid(e: React.MouseEvent<HTMLButtonElement>, entry: string): void; onChangeAvoid(e: React.MouseEvent<HTMLButtonElement>, index: number): void;
onClickDelete: React.MouseEventHandler<HTMLButtonElement>; onClickDelete: React.MouseEventHandler<HTMLButtonElement>;
}; };
@ -76,21 +69,20 @@ export function EditableCard(props: EditableCardProps) {
return ( return (
<Card title={props.field.name} draggable footer={footer}> <Card title={props.field.name} draggable footer={footer}>
<ul> <ul>
{Object.keys(props.field.pronouns).map((pronoun, index) => { {props.field.values.map((value, index) => {
const choice = props.field.pronouns[pronoun];
return ( return (
<li className="flex justify-between my-1 items-center" key={index}> <li className="flex justify-between my-1 items-center" key={index}>
<TextInput <TextInput
value={pronoun} value={value.value}
prevValue={pronoun} prevValue={value.value}
onChange={props.onChangePronoun} onChange={props.onChangePronoun}
/> />
<div className="rounded-md"> <div className="rounded-md">
<button <button
type="button" type="button"
onClick={(e) => props.onChangeFavourite(e, pronoun)} onClick={(e) => props.onChangeFavourite(e, index)}
className={`${ className={`${
choice == PronounChoice.favourite value.status == WordStatus.Favourite
? "bg-slate-500" ? "bg-slate-500"
: "bg-slate-600" : "bg-slate-600"
} text-white hover:bg-slate-400 p-2`} } text-white hover:bg-slate-400 p-2`}
@ -99,9 +91,9 @@ export function EditableCard(props: EditableCardProps) {
</button> </button>
<button <button
type="button" type="button"
onClick={(e) => props.onChangeOkay(e, pronoun)} onClick={(e) => props.onChangeOkay(e, index)}
className={`${ className={`${
choice == PronounChoice.okay value.status == WordStatus.Okay
? "bg-slate-500" ? "bg-slate-500"
: "bg-slate-600" : "bg-slate-600"
} text-white hover:bg-slate-400 p-2`} } text-white hover:bg-slate-400 p-2`}
@ -110,9 +102,9 @@ export function EditableCard(props: EditableCardProps) {
</button> </button>
<button <button
type="button" type="button"
onClick={(e) => props.onChangeJokingly(e, pronoun)} onClick={(e) => props.onChangeJokingly(e, index)}
className={`${ className={`${
choice == PronounChoice.jokingly value.status == WordStatus.Jokingly
? "bg-slate-500" ? "bg-slate-500"
: "bg-slate-600" : "bg-slate-600"
} text-white hover:bg-slate-400 p-2`} } text-white hover:bg-slate-400 p-2`}
@ -121,9 +113,9 @@ export function EditableCard(props: EditableCardProps) {
</button> </button>
<button <button
type="button" type="button"
onClick={(e) => props.onChangeFriends(e, pronoun)} onClick={(e) => props.onChangeFriends(e, index)}
className={`${ className={`${
choice == PronounChoice.friendsOnly value.status == WordStatus.FriendsOnly
? "bg-slate-500" ? "bg-slate-500"
: "bg-slate-600" : "bg-slate-600"
} text-white hover:bg-slate-400 p-2`} } text-white hover:bg-slate-400 p-2`}
@ -132,9 +124,9 @@ export function EditableCard(props: EditableCardProps) {
</button> </button>
<button <button
type="button" type="button"
onClick={(e) => props.onChangeAvoid(e, pronoun)} onClick={(e) => props.onChangeAvoid(e, index)}
className={`${ className={`${
choice == PronounChoice.avoid value.status == WordStatus.Avoid
? "bg-slate-500" ? "bg-slate-500"
: "bg-slate-600" : "bg-slate-600"
} text-white hover:bg-slate-400 p-2`} } text-white hover:bg-slate-400 p-2`}
@ -143,7 +135,7 @@ export function EditableCard(props: EditableCardProps) {
</button> </button>
<button <button
type="button" type="button"
onClick={(e) => props.onDeletePronoun(e, pronoun)} onClick={(e) => props.onDeletePronoun(e, index)}
className="bg-red-600 dark:bg-red-700 hover:bg-red-700 hover:dark:bg-red-800 p-2" className="bg-red-600 dark:bg-red-700 hover:bg-red-700 hover:dark:bg-red-800 p-2"
> >
<Trash3 /> <Trash3 />

View File

@ -10,13 +10,9 @@ import { ReactSortable } from "react-sortablejs";
import { useRecoilState, useRecoilValue } from "recoil"; import { useRecoilState, useRecoilValue } from "recoil";
import Button, { ButtonStyle } from "../../components/Button"; import Button, { ButtonStyle } from "../../components/Button";
import { import { EditableCard, EditField } from "../../components/Editable";
EditableCard,
EditField,
PronounChoice,
} from "../../components/Editable";
import Loading from "../../components/Loading"; import Loading from "../../components/Loading";
import { fetchAPI, Field, MeUser } from "../../lib/api-fetch"; import { fetchAPI, Field, MeUser, WordStatus } from "../../lib/api-fetch";
import { themeState, userState } from "../../lib/state"; import { themeState, userState } from "../../lib/state";
import toast from "../../lib/toast"; import toast from "../../lib/toast";
@ -31,23 +27,11 @@ export default function Index() {
const field: EditField = { const field: EditField = {
id: i, id: i,
name: f.name, name: f.name,
pronouns: {}, values: [],
}; };
f.favourite?.forEach((val) => { f.entries?.forEach((entry) => {
field.pronouns[val] = PronounChoice.favourite; field.values.push(entry);
});
f.okay?.forEach((val) => {
field.pronouns[val] = PronounChoice.okay;
});
f.jokingly?.forEach((val) => {
field.pronouns[val] = PronounChoice.jokingly;
});
f.friends_only?.forEach((val) => {
field.pronouns[val] = PronounChoice.friendsOnly;
});
f.avoid?.forEach((val) => {
field.pronouns[val] = PronounChoice.avoid;
}); });
return field; return field;
@ -67,7 +51,7 @@ export default function Index() {
setFields([ setFields([
...fields, ...fields,
{ id: lastId + 1, name: `Field #${lastId + 2}`, pronouns: {} }, { id: lastId + 1, name: `Field #${lastId + 2}`, values: [] },
]); ]);
}; };
@ -176,43 +160,43 @@ export default function Index() {
e.target.attributes.getNamedItem("data-prev-value")?.value; e.target.attributes.getNamedItem("data-prev-value")?.value;
if (!prev || !e.target.value) return; if (!prev || !e.target.value) return;
const choice = field.pronouns[prev]; const idx = field.values.findIndex((val) => val.value === prev);
delete field.pronouns[prev]; if (idx !== -1) {
field.values[idx].value = e.target.value;
field.pronouns[e.target.value] = choice; }
setFields([...fields]); setFields([...fields]);
}} }}
onAddPronoun={(pronoun) => { onAddPronoun={(pronoun) => {
field.pronouns[pronoun] = PronounChoice.okay; field.values.push({ value: pronoun, status: WordStatus.Okay });
setFields([...fields]); setFields([...fields]);
}} }}
onDeletePronoun={(e, pronoun) => { onDeletePronoun={(e, index) => {
delete field.pronouns[pronoun]; delete field.values[index];
setFields([...fields]); setFields([...fields]);
}} }}
onChangeName={(e) => { onChangeName={(e) => {
field.name = e.target.value; field.name = e.target.value;
setFields([...fields]); setFields([...fields]);
}} }}
onChangeFavourite={(e, entry: string) => { onChangeFavourite={(e, index) => {
field.pronouns[entry] = PronounChoice.favourite; field.values[index].status = WordStatus.Favourite;
setFields([...fields]); setFields([...fields]);
}} }}
onChangeOkay={(e, entry: string) => { onChangeOkay={(e, index) => {
field.pronouns[entry] = PronounChoice.okay; field.values[index].status = WordStatus.Okay;
setFields([...fields]); setFields([...fields]);
}} }}
onChangeJokingly={(e, entry: string) => { onChangeJokingly={(e, index) => {
field.pronouns[entry] = PronounChoice.jokingly; field.values[index].status = WordStatus.Jokingly;
setFields([...fields]); setFields([...fields]);
}} }}
onChangeFriends={(e, entry: string) => { onChangeFriends={(e, index) => {
field.pronouns[entry] = PronounChoice.friendsOnly; field.values[index].status = WordStatus.FriendsOnly;
setFields([...fields]); setFields([...fields]);
}} }}
onChangeAvoid={(e, entry: string) => { onChangeAvoid={(e, index) => {
field.pronouns[entry] = PronounChoice.avoid; field.values[index].status = WordStatus.Avoid;
setFields([...fields]); setFields([...fields]);
}} }}
onClickDelete={(_) => { onClickDelete={(_) => {
@ -233,8 +217,10 @@ function fieldsEqual(arr1: EditField[], arr2: EditField[]) {
if (!arr1.every((_, i) => arr1[i].id === arr2[i].id)) return false; if (!arr1.every((_, i) => arr1[i].id === arr2[i].id)) return false;
return arr1.every((_, i) => return arr1.every((_, i) =>
Object.keys(arr1[i].pronouns).every( arr1[i].values.every(
(val) => arr1[i].pronouns[val] === arr2[i].pronouns[val] (val, j) =>
val.value === arr2[i].values[j].value &&
val.status === arr2[i].values[j].status
) )
); );
} }
@ -247,32 +233,10 @@ async function updateUser(args: {
const newFields = args.fields.map((editField) => { const newFields = args.fields.map((editField) => {
const field: Field = { const field: Field = {
name: editField.name, name: editField.name,
favourite: [], entries: [],
okay: [],
jokingly: [],
friends_only: [],
avoid: [],
}; };
Object.keys(editField.pronouns).forEach((pronoun) => { field.entries = [...editField.values];
switch (editField.pronouns[pronoun]) {
case PronounChoice.favourite:
field.favourite!.push(pronoun);
break;
case PronounChoice.okay:
field.okay!.push(pronoun);
break;
case PronounChoice.jokingly:
field.jokingly!.push(pronoun);
break;
case PronounChoice.friendsOnly:
field.friends_only!.push(pronoun);
break;
case PronounChoice.avoid:
field.avoid!.push(pronoun);
break;
}
});
return field; return field;
}); });