diff --git a/components/RecordForm/RecordForm.jsx b/components/RecordForm/RecordForm.jsx index 6daae56..3a954ef 100644 --- a/components/RecordForm/RecordForm.jsx +++ b/components/RecordForm/RecordForm.jsx @@ -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); @@ -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: ( - <> - - No institutions were added yet - - Create your first institution - - - ), - 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: ( - <> - - Cannot check previos record - - Try to reload the page - - ), - errorMessage: error.stack, - image: "/server-down.svg", - }); - } - }, + defaultValues: async () => + getDefaultValues({ + setFormOverlay, + setWarningState, + handleInstitutionCreate: formMethods.handlers.handleInstitutionCreate, + }), }); const institutionsFieldArray = useFieldArray({ control, @@ -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 }); } })} > diff --git a/components/RecordForm/FormStateOverlay.jsx b/components/RecordForm/components/FormStateOverlay.jsx similarity index 100% rename from components/RecordForm/FormStateOverlay.jsx rename to components/RecordForm/components/FormStateOverlay.jsx diff --git a/components/RecordForm/FormWarning.jsx b/components/RecordForm/components/FormWarning.jsx similarity index 100% rename from components/RecordForm/FormWarning.jsx rename to components/RecordForm/components/FormWarning.jsx diff --git a/components/RecordForm/components/index.js b/components/RecordForm/components/index.js new file mode 100644 index 0000000..a50c9fd --- /dev/null +++ b/components/RecordForm/components/index.js @@ -0,0 +1,2 @@ +export { FormStateOverlay } from "./FormStateOverlay"; +export { FormWarning } from "./FormWarning"; diff --git a/components/RecordForm/handlers/handleEmptyState.jsx b/components/RecordForm/handlers/handleEmptyState.jsx new file mode 100644 index 0000000..c87d90d --- /dev/null +++ b/components/RecordForm/handlers/handleEmptyState.jsx @@ -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: ( + <> + + No institutions were added yet + + Create your first institution + + + ), + image: "/empty.svg", + }); +} diff --git a/components/RecordForm/handlers/handleFetchError.tsx b/components/RecordForm/handlers/handleFetchError.tsx new file mode 100644 index 0000000..6d8a55c --- /dev/null +++ b/components/RecordForm/handlers/handleFetchError.tsx @@ -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> +} + +interface OverlayProps { + children: React.ReactNode; + errorMessage?: string; + image?: string; +} + +export function handleFetchError({ error, setFormOverlay }: handleFetchErrorProps): void { + + setFormOverlay({ + children: ( + <> + + Cannot check previos record + + Try to reload the page + + ), + errorMessage: error.stack, + image: "/server-down.svg", + }); +} diff --git a/components/RecordForm/handlers/handleRecordExist.jsx b/components/RecordForm/handlers/handleRecordExist.jsx new file mode 100644 index 0000000..5324eb8 --- /dev/null +++ b/components/RecordForm/handlers/handleRecordExist.jsx @@ -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, + }); +} diff --git a/components/RecordForm/handlers/handleSavingError.jsx b/components/RecordForm/handlers/handleSavingError.jsx new file mode 100644 index 0000000..22cb9e0 --- /dev/null +++ b/components/RecordForm/handlers/handleSavingError.jsx @@ -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, + }); +} diff --git a/components/RecordForm/handlers/handleSavingSuccess.jsx b/components/RecordForm/handlers/handleSavingSuccess.jsx new file mode 100644 index 0000000..bd7846e --- /dev/null +++ b/components/RecordForm/handlers/handleSavingSuccess.jsx @@ -0,0 +1,11 @@ +/* +Root element of the form +*/ +"use client"; +export function handleSavingSuccess({ toast }) { + toast({ + title: "Record saved", + status: "success", + duration: 3000, + }); +} diff --git a/components/RecordForm/handlers/index.js b/components/RecordForm/handlers/index.js new file mode 100644 index 0000000..d569ee5 --- /dev/null +++ b/components/RecordForm/handlers/index.js @@ -0,0 +1,5 @@ +export { handleEmptyState } from "./handleEmptyState"; +export { handleFetchError } from "./handleFetchError"; +export { handleRecordExist } from "./handleRecordExist"; +export { handleSavingError } from "./handleSavingError"; +export { handleSavingSuccess } from "./handleSavingSuccess"; diff --git a/components/RecordForm/utils/getDefaultValues.js b/components/RecordForm/utils/getDefaultValues.js index c14c53f..f18d08a 100644 --- a/components/RecordForm/utils/getDefaultValues.js +++ b/components/RecordForm/utils/getDefaultValues.js @@ -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, diff --git a/components/RecordForm/utils/index.js b/components/RecordForm/utils/index.js new file mode 100644 index 0000000..5489b96 --- /dev/null +++ b/components/RecordForm/utils/index.js @@ -0,0 +1,2 @@ +export { getDefaultValues } from "./getDefaultValues"; +export { isInCurrentMonth } from "./isDateInCurrentMonth"; diff --git a/handlers/handleFormSubmit.js b/handlers/handleFormSubmit.js deleted file mode 100644 index 2c1ba30..0000000 --- a/handlers/handleFormSubmit.js +++ /dev/null @@ -1,10 +0,0 @@ -import { appendRecord } from "serverActions/appendRecord"; - -export async function handleFormSubmit({ formData, setErrorMessage }) { - try { - await appendRecord(formData); - console.log("Record appended successfully."); - } catch (error) { - setErrorMessage(error); // Set error message in state - } -}