Persist manual ELO form to local storage

Persist manual ELO form to local storage
This commit is contained in:
Timothy Armes
2023-11-28 17:44:14 +01:00
committed by Owen Rees
parent 8caabe810a
commit a2289f6181
4 changed files with 131 additions and 6 deletions
+36 -6
View File
@@ -1,7 +1,7 @@
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { last } from "lodash";
import { isEmpty, isNil, last } from "lodash";
import { useTranslations } from "next-intl";
import { FormProvider, useFieldArray, useForm } from "react-hook-form";
import { IoAdd, IoCloseOutline } from "react-icons/io5";
@@ -11,12 +11,13 @@ import { z } from "zod";
import { RadioGroupField } from "@/components/form/RadioGroupField";
import { SelectField } from "@/components/form/SelectField";
import { TextField } from "@/components/form/TextField";
import useFormPersist from "@/hooks/useFormPersist";
import { getNewRating } from "@/utils/eloCalculator";
import { KFactor } from "./KFactor";
const resultsSchema = z.object({
currentElo: z.number().int().positive(),
currentElo: z.number().int().positive().nullish(),
kFactor: z.enum(["40", "30", "20", "15", "10"]),
games: z.array(
z.object({
@@ -40,6 +41,7 @@ export const ManualEloForm = () => {
const form = useForm<EloFormValues>({
resolver: zodResolver(resultsSchema),
defaultValues: {
currentElo: null,
kFactor: "20",
games: [{}],
},
@@ -54,6 +56,12 @@ export const ManualEloForm = () => {
name: "games",
});
useFormPersist("manualElo", {
watch: form.watch,
setValue: form.setValue,
storage: window.localStorage,
});
const onSubmit = async (data: EloFormValues) => {};
const [currentElo, kFactor, games] = form.watch([
@@ -62,6 +70,13 @@ export const ManualEloForm = () => {
"games",
]);
const isDefault =
isEmpty(currentElo) &&
kFactor === "20" &&
games?.length === 1 &&
(isEmpty(games[0]) ||
(isEmpty(games[0]?.opponentElo) && isEmpty(games[0]?.result)));
type Deltas = {
rating: number;
deltas: { rating: number; delta: number | undefined }[];
@@ -70,7 +85,11 @@ export const ManualEloForm = () => {
const calculations = !Number.isNaN(currentElo)
? (games ?? []).reduce<Deltas>(
(acc, game) => {
if (!Number.isNaN(game?.opponentElo) && game?.result) {
if (
!isNil(game?.opponentElo) &&
!Number.isNaN(game?.opponentElo) &&
game?.result
) {
const result =
game?.result === "win" ? 1 : game?.result === "loss" ? 0 : 0.5;
@@ -136,8 +155,8 @@ export const ManualEloForm = () => {
<div className="flex w-full flex-col gap-6 sm:gap-2">
{gameFields.map((game, i) => {
return (
<div key={i} className="flex w-full flex-col">
<div key={i} className="flex w-full items-center space-x-2">
<div key={game.id} className="flex w-full flex-col">
<div className="flex w-full items-center space-x-2">
<div className="grid w-full grid-cols-1 gap-4 sm:grid-cols-2">
<TextField
name={`games.${i}.opponentElo`}
@@ -223,7 +242,18 @@ export const ManualEloForm = () => {
</div>
)}
<div className="mt-8 flex justify-end">
<div className="mt-8 flex justify-end gap-4">
{!isDefault && (
<button
onClick={() => {
form.reset();
}}
type="button"
className="px-5 py-3 text-center text-sm font-medium text-primary-600 hover:text-primary-800 focus:outline-none focus:ring-4 focus:ring-primary-300 disabled:opacity-25 dark:text-white dark:hover:text-primary-700 dark:focus:ring-primary-800 sm:w-fit"
>
{t("clearButton")}
</button>
)}
<button
onClick={() => {
appendGame({});