Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactored RecordForm #91

Merged
merged 1 commit into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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.

Loading