diff --git a/components/RecordForm/FormWarning.jsx b/components/RecordForm/FormWarning.jsx new file mode 100644 index 0000000..6e13780 --- /dev/null +++ b/components/RecordForm/FormWarning.jsx @@ -0,0 +1,37 @@ +import { + Button, + Accordion, + AccordionButton, + AccordionItem, + AccordionIcon, + Box, + AccordionPanel, + Text, +} from "@chakra-ui/react"; + +import Link from "next/link"; + +export function FormWarning({ heading, message, onHide }) { + return ( + + + +

+ + + {heading} + + + +

+ + {message} + + +
+
+
+ ); +} diff --git a/components/RecordForm/RecordForm.jsx b/components/RecordForm/RecordForm.jsx index 300dd4e..1a4d854 100644 --- a/components/RecordForm/RecordForm.jsx +++ b/components/RecordForm/RecordForm.jsx @@ -15,13 +15,17 @@ import { FormHeader } from "~/FormHeader"; import { handleInstitution } from "handlers"; import { useRouter } from "next/navigation"; import { appendRecord } from "serverActions/appendRecord"; -import { getLatestRecord } from "serverActions/getLatestRecord"; +// import { getLatestRecord } from "serverActions/getLatestRecord"; import { FetchingErrorState } from "./FetchingErrorState"; +import { getDefaultValues } from "./utils/getDefaultValues"; +import { isInCurrentMonth } from "./utils/isDateInCurrentMonth"; +import { FormWarning } from "./FormWarning"; export function RecordForm() { const [isInstitutionOpen, setIsInstitutionOpen] = useState(false); const [selectedInstitutionIndex, setSelectedInstitutionIndex] = useState(0); const [errorState, setErrorState] = useState(false); + const [warningState, setWarningState] = useState(null); const toast = useToast({ position: "top" }); const router = useRouter(); const arrayName = "institutions"; @@ -29,7 +33,22 @@ export function RecordForm() { const { control, ...form } = useForm({ defaultValues: async () => { try { - const initialValues = await getLatestRecord(); + const initialValues = await getDefaultValues(); + if (initialValues === null) { + console.log("no def values"); + } 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) { setErrorState(error.stack); @@ -75,44 +94,58 @@ export function RecordForm() { return ( {isInstitutionOpen || ( - - - - - } - /> + }} + variant="outline" + > + Cancel + + + + } + /> + {warningState?.isVisible && ( + + setWarningState((current) => ({ + ...current, + isVisible: false, + })) + } + /> + )} + )} + {form.formState.isLoading ? ( ) : errorState ? ( diff --git a/components/RecordForm/SlowLoadingToast.jsx b/components/RecordForm/SlowLoadingToast.jsx deleted file mode 100644 index 3b041c7..0000000 --- a/components/RecordForm/SlowLoadingToast.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import { useToast } from "@chakra-ui/react"; - -export function SlowLoadingToast() { - const toast = useToast(); - toast({ - title: "Account created.", - description: "We've created your account for you.", - status: "success", - duration: 5000, - isClosable: true, - }); -} diff --git a/components/RecordForm/utils/getDefaultValues.js b/components/RecordForm/utils/getDefaultValues.js new file mode 100644 index 0000000..c14c53f --- /dev/null +++ b/components/RecordForm/utils/getDefaultValues.js @@ -0,0 +1,23 @@ +import { getLatestRecord } from "serverActions/getLatestRecord"; + +export async function getDefaultValues() { + /** + * Getting initial values for the RecordForm + * + * @returns object to use as react-form-hook defaultValues for RecordForm + * or null if no records in db + */ + + const latestRecord = await getLatestRecord(); + if (latestRecord === null) return null; + + const initialValues = { + date: latestRecord.date, + institutions: latestRecord.institutions.map((institution) => ({ + ...institution, + isDeleted: false, + })), + }; + + return initialValues; +} diff --git a/components/RecordForm/utils/isDateInCurrentMonth.js b/components/RecordForm/utils/isDateInCurrentMonth.js new file mode 100644 index 0000000..0ddc72d --- /dev/null +++ b/components/RecordForm/utils/isDateInCurrentMonth.js @@ -0,0 +1,15 @@ +export function isInCurrentMonth(unixDateInMs) { + /** + * Check if provided unix date is in current month + * + * @returns boolean + */ + + const date = new Date(unixDateInMs); + const now = new Date(); + + return ( + date.getFullYear() === now.getFullYear() && + date.getMonth() === now.getMonth() + ); +} diff --git a/serverActions/getLatestRecord.js b/serverActions/getLatestRecord.js index 1de28ee..c5d8f7e 100644 --- a/serverActions/getLatestRecord.js +++ b/serverActions/getLatestRecord.js @@ -1,40 +1,36 @@ -/* -Server Action used to get latest record from mongodb. - -Latest record then transfomed into format, which is used by react-hook-form in RecordForm -as defaultValues. -*/ - -// TODO pass errors to RecordForm - "use server"; import connect from "utils/mongooseConnect"; import Record from "models/record"; export async function getLatestRecord() { - try { - await connect(); - const latestRecord = await Record.find() - .sort({ createdAt: -1 }) - .limit(1) - .exec(); - const institutionsList = latestRecord[0]?.institutions.toObject({ - transform: function (doc, ret) { - delete ret._id; - return ret; - }, - }); + /** + * Getting latest record from mongodb + * + * @throws Error retreiving record, when mongoose can't perform Record.find + * + * @returns list of institutions with assets + * to be used by react-hook-form in RecordForm as defaultValues + */ - const initialValues = { - institutions: institutionsList?.map((institution) => ({ - ...institution, - isDeleted: false, - })), - }; + await connect(); - return initialValues; + let recordsList = null; + try { + recordsList = await Record.find().sort({ createdAt: -1 }).limit(1).exec(); } catch (error) { - throw error; + throw new Error("Error retreiving record:", error.message); } + + if (recordsList.length === 0) return null; + + const latestRecord = recordsList[0].toObject({ + transform: function (doc, ret) { + delete ret._id; + delete ret.__v; + return ret; + }, + }); + + return latestRecord; } diff --git a/utils/mongooseConnect.js b/utils/mongooseConnect.js index 28be661..41ec701 100644 --- a/utils/mongooseConnect.js +++ b/utils/mongooseConnect.js @@ -3,9 +3,9 @@ import mongoose from "mongoose"; async function connect() { try { await mongoose.connect(process.env.MONGO_URI); - console.log("Database connected!"); + console.info("Database connected"); } catch (error) { - throw ("MongooseConnect error:", error); + throw ("mongooseConnect error:", error.message); } }