Skip to content

Commit

Permalink
refactored RecordForm
Browse files Browse the repository at this point in the history
- extracted handlers
- tried to migrate handler to typescript
  • Loading branch information
skorphil committed Mar 16, 2024
1 parent 12ce0ce commit 0621353
Show file tree
Hide file tree
Showing 13 changed files with 167 additions and 93 deletions.
94 changes: 18 additions & 76 deletions components/RecordForm/RecordForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,21 @@ Root element of the form

"use client";

import { useForm, FormProvider, useFieldArray } from "react-hook-form";
// import { DevTool } from "@hookform/devtools";
import classes from "./RecordForm.module.css";
import { Button, Progress, useToast, Heading, Text } from "@chakra-ui/react";
import { useForm, FormProvider, useFieldArray } from "react-hook-form";
import { useRouter } from "next/navigation";
import { useState } from "react";

import { Button, Progress, useToast } from "@chakra-ui/react";
import { InstitutionsList } from "components/InstitutionsList";
import { FormHeader } from "~/FormHeader";
// import { DevTool } from "@hookform/devtools";
import { handleInstitution } from "handlers";
import { useRouter } from "next/navigation";
import { FormHeader } from "components/FormHeader";
import { FormStateOverlay, FormWarning } from "./components";

import { appendRecord } from "serverActions/appendRecord";
// import { getLatestRecord } from "serverActions/getLatestRecord";
import { FormStateOverlay } from "./FormStateOverlay";
import { getDefaultValues } from "./utils/getDefaultValues";
import { isInCurrentMonth } from "./utils/isDateInCurrentMonth";
import { FormWarning } from "./FormWarning";
import { getDefaultValues } from "./utils";
import { handleInstitution } from "handlers";
import { handleSavingSuccess, handleSavingError } from "./handlers";

export function RecordForm() {
const [isInstitutionOpen, setIsInstitutionOpen] = useState(false);
Expand All @@ -29,61 +28,13 @@ export function RecordForm() {
const toast = useToast({ position: "top" });
const router = useRouter();
const arrayName = "institutions";

const { control, ...form } = useForm({
defaultValues: async () => {
try {
const initialValues = await getDefaultValues();
if (initialValues === null) {
setFormOverlay({
children: (
<>
<Heading as="h1" size="md">
No institutions were added yet
</Heading>
<Text>Create your first institution</Text>
<Button
mt={2}
onClick={() => {
formMethods.handlers.handleInstitutionCreate();
setFormOverlay(null);
}}
>
Add institution
</Button>
</>
),
image: "/empty.svg",
});
} else if (isInCurrentMonth(initialValues.date)) {
setWarningState({
heading: `Record from ${new Date(
initialValues.date
).toLocaleDateString("en-US", {
day: "numeric",
month: "long",
})} will be replaced`,
message: `There is a saved record for this month already.
Saving current record will override that.`,
isVisible: true,
});
}
return initialValues;
} catch (error) {
setFormOverlay({
children: (
<>
<Heading as="h1" size="md">
Cannot check previos record
</Heading>
<Text>Try to reload the page</Text>
</>
),
errorMessage: error.stack,
image: "/server-down.svg",
});
}
},
defaultValues: async () =>
getDefaultValues({
setFormOverlay,
setWarningState,
handleInstitutionCreate: formMethods.handlers.handleInstitutionCreate,
}),
});
const institutionsFieldArray = useFieldArray({
control,
Expand Down Expand Up @@ -143,18 +94,9 @@ export function RecordForm() {
try {
await appendRecord(data);
router.push("/");
toast({
title: "Record saved",
status: "success",
duration: 3000,
});
handleSavingSuccess({ toast });
} catch (error) {
toast({
title: "Error saving record",
description: error.message,
status: "error",
isClosable: true,
});
handleSavingError({ toast, error });
}
})}
>
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 2 additions & 0 deletions components/RecordForm/components/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { FormStateOverlay } from "./FormStateOverlay";
export { FormWarning } from "./FormWarning";
28 changes: 28 additions & 0 deletions components/RecordForm/handlers/handleEmptyState.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
Root element of the form
*/
"use client";
import { Button, Heading, Text } from "@chakra-ui/react";

export function handleEmptyState({ setFormOverlay, handleInstitutionCreate }) {
setFormOverlay({
children: (
<>
<Heading as="h1" size="md">
No institutions were added yet
</Heading>
<Text>Create your first institution</Text>
<Button
mt={2}
onClick={() => {
handleInstitutionCreate();
setFormOverlay(null);
}}
>
Add institution
</Button>
</>
),
image: "/empty.svg",
});
}
32 changes: 32 additions & 0 deletions components/RecordForm/handlers/handleFetchError.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Root element of the form
*/
"use client";
import { Heading, Text } from "@chakra-ui/react";

interface handleFetchErrorProps {
error: Error
setFormOverlay: React.Dispatch<React.SetStateAction<OverlayProps>>
}

interface OverlayProps {
children: React.ReactNode;
errorMessage?: string;
image?: string;
}

export function handleFetchError({ error, setFormOverlay }: handleFetchErrorProps): void {

setFormOverlay({
children: (
<>
<Heading as="h1" size="md">
Cannot check previos record
</Heading>
<Text>Try to reload the page</Text>
</>
),
errorMessage: error.stack,
image: "/server-down.svg",
});
}
18 changes: 18 additions & 0 deletions components/RecordForm/handlers/handleRecordExist.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
Root element of the form
*/
"use client";
export function handleRecordExist({ existingRecordDate, setWarningState }) {
setWarningState({
heading: `Record from ${new Date(existingRecordDate).toLocaleDateString(
"en-US",
{
day: "numeric",
month: "long",
}
)} will be replaced`,
message: `There is a saved record for this month already.
Saving current record will override that.`,
isVisible: true,
});
}
12 changes: 12 additions & 0 deletions components/RecordForm/handlers/handleSavingError.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
Root element of the form
*/
"use client";
export function handleSavingError({ toast, error }) {
toast({
title: "Error saving record",
description: error.message,
status: "error",
isClosable: true,
});
}
11 changes: 11 additions & 0 deletions components/RecordForm/handlers/handleSavingSuccess.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
Root element of the form
*/
"use client";
export function handleSavingSuccess({ toast }) {
toast({
title: "Record saved",
status: "success",
duration: 3000,
});
}
5 changes: 5 additions & 0 deletions components/RecordForm/handlers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export { handleEmptyState } from "./handleEmptyState";
export { handleFetchError } from "./handleFetchError";
export { handleRecordExist } from "./handleRecordExist";
export { handleSavingError } from "./handleSavingError";
export { handleSavingSuccess } from "./handleSavingSuccess";
46 changes: 39 additions & 7 deletions components/RecordForm/utils/getDefaultValues.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,50 @@
import { getLatestRecord } from "serverActions/getLatestRecord";
import {
handleFetchError,
handleEmptyState,
handleRecordExist,
} from "../handlers";
import { isInCurrentMonth } from "./isDateInCurrentMonth";

export async function getDefaultValues() {
export async function getDefaultValues({
setFormOverlay,
handleInstitutionCreate,
setWarningState,
}) {
/**
* Getting initial values for the RecordForm
* Get initial values for the RecordForm and handling errors and warnings,
* based on received values
*
* @returns object to use as react-form-hook defaultValues for RecordForm
* or null if no records in db
* @param setFormOverlay - state setter from RecordForm
* @param setWarningState - state setter from RecordForm
* @param handleInstitutionCreate - handler from formMethods whith arguments
* from RecordForm
*
* @returns object to use as react-form-hook defaultValues for {@link RecordForm}
* or void if errors / empty states
*/

const latestRecord = await getLatestRecord();
if (latestRecord === null) return null;
let latestRecord = null;
try {
latestRecord = await getLatestRecord();
} catch (error) {
handleFetchError({ error, setFormOverlay });
return;
}
if (latestRecord === null) {
handleEmptyState({
setFormOverlay,
handleInstitutionCreate,
});
return null;
} else if (isInCurrentMonth(latestRecord.date)) {
handleRecordExist({
existingRecordDate: latestRecord.date,
setWarningState,
});
}

const initialValues = {
date: latestRecord.date,
institutions: latestRecord.institutions.map((institution) => ({
...institution,
isDeleted: false,
Expand Down
2 changes: 2 additions & 0 deletions components/RecordForm/utils/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { getDefaultValues } from "./getDefaultValues";
export { isInCurrentMonth } from "./isDateInCurrentMonth";
10 changes: 0 additions & 10 deletions handlers/handleFormSubmit.js

This file was deleted.

0 comments on commit 0621353

Please sign in to comment.