diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 4accb66..dce8b99 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -49,17 +49,5 @@ module.exports = { "import/first": "error", "import/newline-after-import": "error", "import/no-duplicates": "error", - "no-restricted-imports": [ - "error", - { - patterns: [ - { - group: [".*"], - message: - 'Please do not use relative imports. Use "@/..." instead. If this breaks something, disable the rule for that file only.', - }, - ], - }, - ], }, }; diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts index c446deb..9a73823 100644 --- a/src/app/api/auth/[...nextauth]/route.ts +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -1,6 +1,6 @@ import NextAuth from "next-auth"; -import authOptions from "@/app/api/auth/[...nextauth]/options"; +import authOptions from "./options"; const handler = NextAuth(authOptions); diff --git a/src/components/AdminDashboard/PendingApplicationDashboard/PendingApplicationInfoModal/FormResponse.tsx b/src/components/AdminDashboard/PendingApplicationDashboard/PendingApplicationInfoModal/FormResponse.tsx index 825632b..3b77398 100644 --- a/src/components/AdminDashboard/PendingApplicationDashboard/PendingApplicationInfoModal/FormResponse.tsx +++ b/src/components/AdminDashboard/PendingApplicationDashboard/PendingApplicationInfoModal/FormResponse.tsx @@ -2,7 +2,7 @@ import { Typography } from "@mui/material"; type FormResponse = { label: string; - value: string; + value: string | number; isListItem?: boolean; }; diff --git a/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/HealthyHabitsTrackingFormList/HealthyHabitsTrackingFormListItem.tsx b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/HealthyHabitsTrackingFormList/HealthyHabitsTrackingFormListItem.tsx new file mode 100644 index 0000000..1f627d8 --- /dev/null +++ b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/HealthyHabitsTrackingFormList/HealthyHabitsTrackingFormListItem.tsx @@ -0,0 +1,57 @@ +"use client"; + +import DeleteIcon from "@mui/icons-material/Delete"; +import DescriptionIcon from "@mui/icons-material/Description"; +import { + Avatar, + Box, + IconButton, + ListItem, + ListItemAvatar, + ListItemText, +} from "@mui/material"; +import { useState } from "react"; + +import HealthyHabitsTrackingFormModal from "@/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/HealthyHabitsTrackingFormList/HealthyHabitsTrackingFormModal"; +import { HealthyHabitsTrackingForm } from "@/types"; +import dayjsUtil from "@/utils/dayjsUtil"; + +type HealthyHabitsTrackingFormListItemProps = { + form: HealthyHabitsTrackingForm; + handleDelete: (form: HealthyHabitsTrackingForm) => void; +}; + +export default function HealthyHabitsTrackingFormListItem({ + form, + handleDelete, +}: HealthyHabitsTrackingFormListItemProps) { + const [open, setOpen] = useState(false); + + return ( + + + + + handleDelete(form)}> + + + + } + > + + + + + + + + ); +} diff --git a/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/HealthyHabitsTrackingFormList/HealthyHabitsTrackingFormModal.tsx b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/HealthyHabitsTrackingFormList/HealthyHabitsTrackingFormModal.tsx new file mode 100644 index 0000000..ec2e49f --- /dev/null +++ b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/HealthyHabitsTrackingFormList/HealthyHabitsTrackingFormModal.tsx @@ -0,0 +1,168 @@ +"use client"; + +import InfoIcon from "@mui/icons-material/Info"; +import { Box, Button, Fade, Modal, Typography } from "@mui/material"; +import { Dispatch, SetStateAction } from "react"; + +import FormResponse from "@/components/AdminDashboard/PendingApplicationDashboard/PendingApplicationInfoModal/FormResponse"; +import { HealthyHabitsTrackingForm } from "@/types"; +import dayjsUtil from "@/utils/dayjsUtil"; + +const style = { + position: "absolute", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + width: "40vw", + maxHeight: "80vh", + overflowY: "auto", + bgcolor: "background.paper", + boxShadow: 2, + p: 4, + display: "flex", + flexDirection: "column", + gap: 2, +}; + +type HealthyHabitsTrackingFormModalProps = { + open: boolean; + setOpen: Dispatch>; + form: HealthyHabitsTrackingForm; +}; + +export default function HealthyHabitsTrackingFormModal({ + form, + open, + setOpen, +}: HealthyHabitsTrackingFormModalProps) { + return ( + <> + setOpen(true)} /> + + setOpen(false)} + closeAfterTransition + > + + + + {dayjsUtil.utc(form.submittedDate).format("MM/DD/YYYY")} + + + + + Devices + + + + + + + + + + + Measurements + + + + + Daily Activity + + + Wellness Rankings + + + + + Goals + + + + + + + + + ); +} diff --git a/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/HealthyHabitsTrackingFormList/index.tsx b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/HealthyHabitsTrackingFormList/index.tsx new file mode 100644 index 0000000..71ec9e9 --- /dev/null +++ b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/HealthyHabitsTrackingFormList/index.tsx @@ -0,0 +1,70 @@ +"use client"; + +import { Box, List, Snackbar, Typography } from "@mui/material"; +import { Dispatch, SetStateAction, useState } from "react"; + +import HealthyHabitsTrackingFormListItem from "@/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/HealthyHabitsTrackingFormList/HealthyHabitsTrackingFormListItem"; +import { handleHealthyHabitsTrackingFormDeletion } from "@/server/api/healthy-habits-tracking-forms/public-mutations"; +import { ClientUser, HealthyHabitsTrackingForm } from "@/types"; + +type HealthyHabitsTrackingFormListProps = { + trackingForms: HealthyHabitsTrackingForm[]; + setTrackingForms: Dispatch>; + user: ClientUser; +}; + +export default function HealthyHabitsTrackingFormList({ + trackingForms, + setTrackingForms, + user, +}: HealthyHabitsTrackingFormListProps) { + const [snackbarOpen, setSnackbarOpen] = useState(false); + const [snackbarMessage, setSnackbarMessage] = useState(""); + + const handleDelete = async (form: HealthyHabitsTrackingForm) => { + const confirm = window.confirm( + "Are you sure you want to delete this health tracking record?", + ); + + if (!confirm) { + return; + } + + setTrackingForms((prevForms) => + prevForms.filter((prevForm) => prevForm._id !== form._id), + ); + + const [, error] = await handleHealthyHabitsTrackingFormDeletion(form, user); + + if (error !== null) { + setSnackbarMessage("An unexpected error occurred."); + } else { + setSnackbarMessage("Form deleted successfully."); + } + + setSnackbarOpen(true); + }; + + return ( + <> + setSnackbarOpen(false)} + message={snackbarMessage} + /> + + Previous forms + + {trackingForms.map((form) => ( + + ))} + + + + ); +} diff --git a/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/ModularBarChart.tsx b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/ModularBarChart.tsx index 45c4cea..72500c7 100644 --- a/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/ModularBarChart.tsx +++ b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/ModularBarChart.tsx @@ -23,13 +23,11 @@ export default function ModularBarChart({ const getChartData = () => { return trackingForms .sort((a, b) => - dayjsUtil(a.submittedDate, "MM/DD/YYYY").diff( - dayjsUtil(b.submittedDate, "MM/DD/YYYY"), - ), + dayjsUtil.utc(a.submittedDate).diff(dayjsUtil.utc(b.submittedDate)), ) .map((form) => ({ value: Number(form[dataKey]) || 0, - label: `Week of ${dayjsUtil(form.submittedDate, "MM/DD/YYYY").format("MM/DD/YY")}`, + label: `Week of ${dayjsUtil.utc(form.submittedDate).format("MM/DD/YY")}`, })); }; diff --git a/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/ModularLineChart.tsx b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/ModularLineChart.tsx index 3467e46..a7e01b1 100644 --- a/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/ModularLineChart.tsx +++ b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/ModularLineChart.tsx @@ -42,13 +42,11 @@ export default function ModularLineChart({ const getChartDataAndSeries = (): ChartConfig => { const sortedData = trackingForms.sort((a, b) => - dayjsUtil(a.submittedDate, "MM/DD/YYYY").diff( - dayjsUtil(b.submittedDate, "MM/DD/YYYY"), - ), + dayjsUtil.utc(a.submittedDate).diff(dayjsUtil.utc(b.submittedDate)), ); const chartData: RegularChartDataPoint[] = sortedData.map((entry) => ({ - x: dayjsUtil(entry.submittedDate, "MM/DD/YYYY").toDate(), + x: dayjsUtil.utc(entry.submittedDate).toDate(), y: entry[dataKey] as number, ...(dataKey2 && { y2: entry[dataKey2] as number }), })); @@ -96,7 +94,7 @@ export default function ModularLineChart({ label: "Date", scaleType: "time", valueFormatter: (value) => - `Week of ${dayjsUtil(value).format("MM/DD/YYYY")}`, + `Week of ${dayjsUtil.utc(value).format("MM/DD/YYYY")}`, tickInterval: chartData.map((item) => item.x), }, ]} diff --git a/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/index.tsx b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/index.tsx index 5456852..1b06fef 100644 --- a/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/index.tsx +++ b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/index.tsx @@ -1,18 +1,42 @@ "use client"; -import { Box } from "@mui/material"; +import { Box, Typography } from "@mui/material"; +import { useState } from "react"; +import HealthyHabitsTrackingFormList from "@/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/HealthyHabitsTrackingFormList"; import ModularBarChart from "@/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/ModularBarChart"; import ModularLineChart from "@/components/ClientDashboard/HealthyHabits/HealthyHabitsHistory/ModularLineChart"; -import { HealthyHabitsTrackingForm } from "@/types"; +import { ClientUser, HealthyHabitsTrackingForm } from "@/types"; type HealthyHabitsHistoryProps = { - trackingForms: HealthyHabitsTrackingForm[]; + initialForms: HealthyHabitsTrackingForm[]; + user: ClientUser; }; export default function HealthyHabitsHistory({ - trackingForms, + initialForms, + user, }: HealthyHabitsHistoryProps) { + const [trackingForms, setTrackingForms] = + useState(initialForms); + + if (trackingForms.length === 0) { + return ( + + No forms submitted yet. + + ); + } + return ( + ); } diff --git a/src/components/ClientDashboard/HealthyHabits/HealthyHabitsTracking.tsx b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsTracking.tsx index 2b4d32e..cd69d5c 100644 --- a/src/components/ClientDashboard/HealthyHabits/HealthyHabitsTracking.tsx +++ b/src/components/ClientDashboard/HealthyHabits/HealthyHabitsTracking.tsx @@ -85,6 +85,7 @@ export default function HealthyHabitsTracking({ const healthyHabitsTrackingForm: HealthyHabitsTrackingForm = { ...data, + submittedDate: dayjsUtil(data.submittedDate).utc().toISOString(), user, }; diff --git a/src/components/ClientDashboard/HealthyHabits/index.tsx b/src/components/ClientDashboard/HealthyHabits/index.tsx index bdd2e0c..9a27fbb 100644 --- a/src/components/ClientDashboard/HealthyHabits/index.tsx +++ b/src/components/ClientDashboard/HealthyHabits/index.tsx @@ -31,7 +31,8 @@ export default function HealthyHabits({ user }: HealthyHabitsProps) { case "history": return ( ); case "info": diff --git a/src/server/api/email-verification-tokens/private-mutations.ts b/src/server/api/email-verification-tokens/private-mutations.ts index adc0834..9e9f748 100644 --- a/src/server/api/email-verification-tokens/private-mutations.ts +++ b/src/server/api/email-verification-tokens/private-mutations.ts @@ -1,10 +1,11 @@ -import { getEmailVerificationTokenByToken } from "@/server/api/email-verification-tokens/queries"; import dbConnect from "@/server/dbConnect"; import { EmailVerificationTokenModel } from "@/server/models"; import { ApiResponse, EmailVerificationToken } from "@/types"; import apiErrors from "@/utils/constants/apiErrors"; import handleMongooseError from "@/utils/handleMongooseError"; +import { getEmailVerificationTokenByToken } from "./queries"; + export async function createEmailVerificationToken( token: string, userId: string, diff --git a/src/server/api/email-verification-tokens/public-mutations.ts b/src/server/api/email-verification-tokens/public-mutations.ts index 3c5f6be..83dfa34 100644 --- a/src/server/api/email-verification-tokens/public-mutations.ts +++ b/src/server/api/email-verification-tokens/public-mutations.ts @@ -1,10 +1,11 @@ "use server"; -import { createEmailVerificationToken } from "@/server/api/email-verification-tokens/private-mutations"; -import { sendEmailVerificationEmail } from "@/server/api/emails/private-mutations"; -import { getUserByEmail } from "@/server/api/users/queries"; import { EmailVerificationToken } from "@/types"; +import { sendEmailVerificationEmail } from "../emails/private-mutations"; +import { getUserByEmail } from "../users/queries"; +import { createEmailVerificationToken } from "./private-mutations"; + export async function handleEmailVerificationTokenRequest( email: string, ): Promise { diff --git a/src/server/api/emails/private-mutations.tsx b/src/server/api/emails/private-mutations.tsx index 2b227ea..72c017e 100644 --- a/src/server/api/emails/private-mutations.tsx +++ b/src/server/api/emails/private-mutations.tsx @@ -5,7 +5,8 @@ import PasswordChangedEmail from "@/components/emails/PasswordChangedEmail"; import RejectionEmail from "@/components/emails/RejectionEmail"; import ResetPasswordEmail from "@/components/emails/ResetPasswordEmail"; import WelcomeEmail from "@/components/emails/WelcomeEmail"; -import sendEmail from "@/server/api/emails/helpers"; + +import sendEmail from "./helpers"; export async function sendPasswordChangeEmail( recipientEmail: string, diff --git a/src/server/api/enrollment-forms/private-mutations.ts b/src/server/api/enrollment-forms/private-mutations.ts index 84a7bba..bd204e2 100644 --- a/src/server/api/enrollment-forms/private-mutations.ts +++ b/src/server/api/enrollment-forms/private-mutations.ts @@ -1,4 +1,3 @@ -import { getEnrollmentFormByEmail } from "@/server/api/enrollment-forms/queries"; import dbConnect from "@/server/dbConnect"; import { EnrollmentFormModel } from "@/server/models"; import { ApiResponse, EnrollmentForm } from "@/types"; @@ -6,6 +5,8 @@ import apiErrors from "@/utils/constants/apiErrors"; import handleMongooseError from "@/utils/handleMongooseError"; import { serializeMongooseObject } from "@/utils/serializeMongooseObject"; +import { getEnrollmentFormByEmail } from "./queries"; + export async function createEnrollmentForm( enrollmentForm: EnrollmentForm, ): Promise> { diff --git a/src/server/api/enrollment-forms/public-mutations.ts b/src/server/api/enrollment-forms/public-mutations.ts index 7d204d0..e2aa4dd 100644 --- a/src/server/api/enrollment-forms/public-mutations.ts +++ b/src/server/api/enrollment-forms/public-mutations.ts @@ -1,11 +1,12 @@ "use server"; -import { handleEmailVerificationTokenRequest } from "@/server/api/email-verification-tokens/public-mutations"; -import { createEnrollmentForm } from "@/server/api/enrollment-forms/private-mutations"; -import { createProgramEnrollmentsFromEnrollmentForm } from "@/server/api/program-enrollments/private-mutations"; -import { createClientUser } from "@/server/api/users/private-mutations"; import { ApiResponse, ClientUser, EnrollmentForm } from "@/types"; +import { handleEmailVerificationTokenRequest } from "../email-verification-tokens/public-mutations"; +import { createProgramEnrollmentsFromEnrollmentForm } from "../program-enrollments/private-mutations"; +import { createClientUser } from "../users/private-mutations"; +import { createEnrollmentForm } from "./private-mutations"; + export async function handleEnrollmentFormSubmission( enrollmentForm: EnrollmentForm, ): Promise> { diff --git a/src/server/api/healthy-habits-tracking-forms/private-mutations.ts b/src/server/api/healthy-habits-tracking-forms/private-mutations.ts index 582d1d1..d6ae1a9 100644 --- a/src/server/api/healthy-habits-tracking-forms/private-mutations.ts +++ b/src/server/api/healthy-habits-tracking-forms/private-mutations.ts @@ -1,11 +1,12 @@ -import { getHealthyHabitsTrackingForm } from "@/server/api/healthy-habits-tracking-forms/queries"; import dbConnect from "@/server/dbConnect"; import { HealthyHabitsTrackingFormModel, UserModel } from "@/server/models"; -import { ApiResponse, HealthyHabitsTrackingForm } from "@/types"; +import { ApiResponse, ClientUser, HealthyHabitsTrackingForm } from "@/types"; import apiErrors from "@/utils/constants/apiErrors"; import handleMongooseError from "@/utils/handleMongooseError"; import { serializeMongooseObject } from "@/utils/serializeMongooseObject"; +import { getHealthyHabitsTrackingForm } from "./queries"; + export async function createHealthyHabitsTrackingForm( healthyHabitsTrackingForm: HealthyHabitsTrackingForm, ): Promise> { @@ -43,3 +44,32 @@ export async function createHealthyHabitsTrackingForm( return [null, handleMongooseError(error)]; } } + +export async function deleteHealthyHabitsTrackingForm( + form: HealthyHabitsTrackingForm, + user: ClientUser, +): Promise> { + await dbConnect(); + + try { + const healthyHabitsTrackingForm = + await HealthyHabitsTrackingFormModel.findByIdAndDelete(form._id).exec(); + + if (!healthyHabitsTrackingForm) { + return [ + null, + apiErrors.healthyHabitsTrackingForm.healthyHabitsTrackingFormNotFound, + ]; + } + + // delete the user's healthy habits tracking form if it exists + await UserModel.findByIdAndUpdate(user._id, { + $pull: { healthyHabitsTrackingForms: form._id }, + }); + + return [serializeMongooseObject(healthyHabitsTrackingForm), null]; + } catch (error) { + console.error(error); + return [null, handleMongooseError(error)]; + } +} diff --git a/src/server/api/healthy-habits-tracking-forms/public-mutations.ts b/src/server/api/healthy-habits-tracking-forms/public-mutations.ts index face44c..a93c212 100644 --- a/src/server/api/healthy-habits-tracking-forms/public-mutations.ts +++ b/src/server/api/healthy-habits-tracking-forms/public-mutations.ts @@ -1,13 +1,61 @@ "use server"; -import { createHealthyHabitsTrackingForm } from "@/server/api/healthy-habits-tracking-forms/private-mutations"; -import { ApiResponse, HealthyHabitsTrackingForm } from "@/types"; +import { ApiResponse, ClientUser, HealthyHabitsTrackingForm } from "@/types"; +import authenticateServerFunction from "@/utils/authenticateServerFunction"; +import apiErrors from "@/utils/constants/apiErrors"; + +import { + createHealthyHabitsTrackingForm, + deleteHealthyHabitsTrackingForm, +} from "./private-mutations"; export async function handleHealthyHabitsTrackingFormSubmission( healthyHabitsTrackingForm: HealthyHabitsTrackingForm, ): Promise> { - const [, error] = await createHealthyHabitsTrackingForm( + const [session, authError] = await authenticateServerFunction(); + + if (authError !== null) { + return [null, authError]; + } + + if ( + session.user.role === "client" && + session.user.email !== healthyHabitsTrackingForm.user.email + ) { + return [null, apiErrors.unauthorized]; + } + + const [, createError] = await createHealthyHabitsTrackingForm( + healthyHabitsTrackingForm, + ); + + if (createError !== null) { + return [null, createError]; + } + + return [null, null]; +} + +export async function handleHealthyHabitsTrackingFormDeletion( + healthyHabitsTrackingForm: HealthyHabitsTrackingForm, + user: ClientUser, +): Promise> { + const [session, authError] = await authenticateServerFunction(); + + if (authError !== null) { + return [null, authError]; + } + + if ( + session.user.role === "client" && + session.user.email !== healthyHabitsTrackingForm.user.email + ) { + return [null, apiErrors.unauthorized]; + } + + const [, error] = await deleteHealthyHabitsTrackingForm( healthyHabitsTrackingForm, + user, ); if (error !== null) { diff --git a/src/server/api/healthy-habits-tracking-forms/queries.ts b/src/server/api/healthy-habits-tracking-forms/queries.ts index 562ae95..0cc9b10 100644 --- a/src/server/api/healthy-habits-tracking-forms/queries.ts +++ b/src/server/api/healthy-habits-tracking-forms/queries.ts @@ -1,4 +1,3 @@ -import { getUserByEmail } from "@/server/api/users/queries"; import dbConnect from "@/server/dbConnect"; import { HealthyHabitsTrackingFormModel } from "@/server/models"; import { ApiResponse, HealthyHabitsTrackingForm } from "@/types"; @@ -6,6 +5,8 @@ import apiErrors from "@/utils/constants/apiErrors"; import handleMongooseError from "@/utils/handleMongooseError"; import { serializeMongooseObject } from "@/utils/serializeMongooseObject"; +import { getUserByEmail } from "../users/queries"; + export async function getHealthyHabitsTrackingForm( email: string, submittedDate: string, diff --git a/src/server/api/password-reset-tokens/private-mutations.ts b/src/server/api/password-reset-tokens/private-mutations.ts index 965e599..955b741 100644 --- a/src/server/api/password-reset-tokens/private-mutations.ts +++ b/src/server/api/password-reset-tokens/private-mutations.ts @@ -1,4 +1,3 @@ -import { getPasswordResetTokenByToken } from "@/server/api/password-reset-tokens/queries"; import dbConnect from "@/server/dbConnect"; import { PasswordResetTokenModel } from "@/server/models"; import { ApiResponse, PasswordResetToken } from "@/types"; @@ -6,6 +5,8 @@ import apiErrors from "@/utils/constants/apiErrors"; import handleMongooseError from "@/utils/handleMongooseError"; import { serializeMongooseObject } from "@/utils/serializeMongooseObject"; +import { getPasswordResetTokenByToken } from "./queries"; + export async function createPasswordResetToken( token: string, userId: string, diff --git a/src/server/api/password-reset-tokens/public-mutations.ts b/src/server/api/password-reset-tokens/public-mutations.ts index 6d00c29..c1c288c 100644 --- a/src/server/api/password-reset-tokens/public-mutations.ts +++ b/src/server/api/password-reset-tokens/public-mutations.ts @@ -1,11 +1,12 @@ "use server"; -import { sendPasswordResetEmail } from "@/server/api/emails/private-mutations"; -import { createPasswordResetToken } from "@/server/api/password-reset-tokens/private-mutations"; -import { getUserByEmail } from "@/server/api/users/queries"; import { PasswordResetToken } from "@/types"; import dayjsUtil from "@/utils/dayjsUtil"; +import { sendPasswordResetEmail } from "../emails/private-mutations"; +import { getUserByEmail } from "../users/queries"; +import { createPasswordResetToken } from "./private-mutations"; + export default async function handlePasswordResetRequest(email: string) { // check if email exists const [user, userError] = await getUserByEmail(email); diff --git a/src/server/api/program-enrollments/private-mutations.ts b/src/server/api/program-enrollments/private-mutations.ts index 451a81d..d15cf61 100644 --- a/src/server/api/program-enrollments/private-mutations.ts +++ b/src/server/api/program-enrollments/private-mutations.ts @@ -1,4 +1,3 @@ -import { getProgramEnrollmentForUser } from "@/server/api/program-enrollments/queries"; import dbConnect from "@/server/dbConnect"; import { ProgramEnrollmentModel, UserModel } from "@/server/models"; import { ApiResponse, EnrollmentForm, ProgramEnrollment, User } from "@/types"; @@ -7,6 +6,8 @@ import dayjsUtil from "@/utils/dayjsUtil"; import handleMongooseError from "@/utils/handleMongooseError"; import { serializeMongooseObject } from "@/utils/serializeMongooseObject"; +import { getProgramEnrollmentForUser } from "./queries"; + export async function createProgramEnrollment( programEnrollment: ProgramEnrollment, ): Promise> { diff --git a/src/server/api/program-enrollments/public-mutations.ts b/src/server/api/program-enrollments/public-mutations.ts index 79dce5a..609c7cb 100644 --- a/src/server/api/program-enrollments/public-mutations.ts +++ b/src/server/api/program-enrollments/public-mutations.ts @@ -1,15 +1,16 @@ "use server"; +import { ProgramEnrollment } from "@/types"; +import authenticateServerFunction from "@/utils/authenticateServerFunction"; + import { sendRejectionEmail, sendWelcomeEmail, -} from "@/server/api/emails/private-mutations"; +} from "../emails/private-mutations"; import { approveProgramEnrollment, rejectProgramEnrollment, -} from "@/server/api/program-enrollments/private-mutations"; -import { ProgramEnrollment } from "@/types"; -import authenticateServerFunction from "@/utils/authenticateServerFunction"; +} from "./private-mutations"; export async function handleRejectProgramApplication( programEnrollment: ProgramEnrollment, diff --git a/src/server/api/users/private-mutations.ts b/src/server/api/users/private-mutations.ts index 8142b6b..62b1ea3 100644 --- a/src/server/api/users/private-mutations.ts +++ b/src/server/api/users/private-mutations.ts @@ -2,7 +2,6 @@ import bcrypt from "bcrypt"; import mongoose from "mongoose"; import { AdminUserRequest } from "@/app/api/users/actions/create-admin-account/route"; -import { getUserByEmail } from "@/server/api/users/queries"; import dbConnect from "@/server/dbConnect"; import { UserModel } from "@/server/models"; import { AdminUser, ApiResponse, ClientUser, User } from "@/types"; @@ -11,6 +10,8 @@ import apiErrors from "@/utils/constants/apiErrors"; import dayjsUtil from "@/utils/dayjsUtil"; import handleMongooseError from "@/utils/handleMongooseError"; +import { getUserByEmail } from "./queries"; + export async function createAdminUser( adminUserRequest: AdminUserRequest, ): Promise> { diff --git a/src/server/api/users/public-mutations.ts b/src/server/api/users/public-mutations.ts index 490c8d4..a27f986 100644 --- a/src/server/api/users/public-mutations.ts +++ b/src/server/api/users/public-mutations.ts @@ -1,22 +1,19 @@ "use server"; - import bcrypt from "bcrypt"; -import { deleteEmailVerificationToken } from "@/server/api/email-verification-tokens/private-mutations"; -import { getEmailVerificationTokenByToken } from "@/server/api/email-verification-tokens/queries"; -import { sendPasswordChangeEmail } from "@/server/api/emails/private-mutations"; -import { deletePasswordResetToken } from "@/server/api/password-reset-tokens/private-mutations"; -import { getPasswordResetTokenByToken } from "@/server/api/password-reset-tokens/queries"; -import { - changePassword, - updateUser, -} from "@/server/api/users/private-mutations"; -import { getUserById } from "@/server/api/users/queries"; import dbConnect from "@/server/dbConnect"; import { ApiResponse } from "@/types"; import authenticateServerFunction from "@/utils/authenticateServerFunction"; import apiErrors from "@/utils/constants/apiErrors"; +import { deleteEmailVerificationToken } from "../email-verification-tokens/private-mutations"; +import { getEmailVerificationTokenByToken } from "../email-verification-tokens/queries"; +import { sendPasswordChangeEmail } from "../emails/private-mutations"; +import { deletePasswordResetToken } from "../password-reset-tokens/private-mutations"; +import { getPasswordResetTokenByToken } from "../password-reset-tokens/queries"; +import { changePassword, updateUser } from "./private-mutations"; +import { getUserById } from "./queries"; + export async function resetPasswordWithToken( token: string, newPassword: string, diff --git a/src/server/api/users/queries.ts b/src/server/api/users/queries.ts index dd8ed20..45ac4bd 100644 --- a/src/server/api/users/queries.ts +++ b/src/server/api/users/queries.ts @@ -22,7 +22,10 @@ async function getUser( const userQuery = UserModel.findOne(filters); if (options?.populateHealthyHabitsTrackingForms) { - userQuery.populate("healthyHabitsTrackingForms"); + userQuery.populate({ + path: "healthyHabitsTrackingForms", + options: { sort: { submittedDate: -1 } }, + }); } if (options?.populateProgramEnrollments) { diff --git a/src/server/models/index.ts b/src/server/models/index.ts index 010106d..829ee0a 100644 --- a/src/server/models/index.ts +++ b/src/server/models/index.ts @@ -1,6 +1,6 @@ -export { default as EmailVerificationTokenModel } from "@/server/models/EmailVerificationToken"; -export { default as EnrollmentFormModel } from "@/server/models/EnrollmentForm"; -export { default as HealthyHabitsTrackingFormModel } from "@/server/models/HealthyHabitsTrackingForm"; -export { default as PasswordResetTokenModel } from "@/server/models/PasswordResetToken"; -export { default as ProgramEnrollmentModel } from "@/server/models/ProgramEnrollment"; -export { default as UserModel } from "@/server/models/User"; +export { default as EmailVerificationTokenModel } from "./EmailVerificationToken"; +export { default as EnrollmentFormModel } from "./EnrollmentForm"; +export { default as HealthyHabitsTrackingFormModel } from "./HealthyHabitsTrackingForm"; +export { default as PasswordResetTokenModel } from "./PasswordResetToken"; +export { default as ProgramEnrollmentModel } from "./ProgramEnrollment"; +export { default as UserModel } from "./User"; diff --git a/src/types/EnrollmentForm/EnrollmentForm.ts b/src/types/EnrollmentForm/EnrollmentForm.ts index f850a47..c073aa1 100644 --- a/src/types/EnrollmentForm/EnrollmentForm.ts +++ b/src/types/EnrollmentForm/EnrollmentForm.ts @@ -1,7 +1,9 @@ -import { GeneralInformationSection } from "@/types/EnrollmentForm/GeneralInformationSection"; -import { ProgramSelectionSection } from "@/types/EnrollmentForm/ProgramSelectionSection"; -import { ProgramSpecificQuestionsSection } from "@/types/EnrollmentForm/ProgramSpecificQuestionsSection"; -import { QualifyingQuestionsSection } from "@/types/EnrollmentForm/QualifyingQuestionsSection"; +import { + GeneralInformationSection, + ProgramSelectionSection, + ProgramSpecificQuestionsSection, + QualifyingQuestionsSection, +} from "."; export type EnrollmentForm = { _id?: string; diff --git a/src/types/EnrollmentForm/index.ts b/src/types/EnrollmentForm/index.ts index 2acaa3d..bf0533b 100644 --- a/src/types/EnrollmentForm/index.ts +++ b/src/types/EnrollmentForm/index.ts @@ -1,5 +1,5 @@ -export * from "@/types/EnrollmentForm/EnrollmentForm"; -export * from "@/types/EnrollmentForm/GeneralInformationSection"; -export * from "@/types/EnrollmentForm/ProgramSelectionSection"; -export * from "@/types/EnrollmentForm/ProgramSpecificQuestionsSection"; -export * from "@/types/EnrollmentForm/QualifyingQuestionsSection"; +export * from "./EnrollmentForm"; +export * from "./GeneralInformationSection"; +export * from "./ProgramSelectionSection"; +export * from "./ProgramSpecificQuestionsSection"; +export * from "./QualifyingQuestionsSection"; diff --git a/src/types/HealthyHabitsTrackingForm.ts b/src/types/HealthyHabitsTrackingForm.ts index 75cd542..3b9be95 100644 --- a/src/types/HealthyHabitsTrackingForm.ts +++ b/src/types/HealthyHabitsTrackingForm.ts @@ -1,6 +1,6 @@ import z from "zod"; -import { User } from "@/types"; +import { User } from "."; export const healthyHabitsValidator = z.object({ submittedDate: z.string(), diff --git a/src/types/ProgramEnrollment.ts b/src/types/ProgramEnrollment.ts index 12096b0..ef6a367 100644 --- a/src/types/ProgramEnrollment.ts +++ b/src/types/ProgramEnrollment.ts @@ -1,4 +1,4 @@ -import { Program, User } from "@/types"; +import { Program, User } from "."; export type ProgramEnrollment = { _id?: string; diff --git a/src/types/User.ts b/src/types/User.ts index d46c642..84bc892 100644 --- a/src/types/User.ts +++ b/src/types/User.ts @@ -2,7 +2,7 @@ import { EnrollmentForm, HealthyHabitsTrackingForm, ProgramEnrollment, -} from "@/types"; +} from "."; export type AdminUser = { _id?: string; diff --git a/src/types/index.ts b/src/types/index.ts index 8e52dca..ef2247b 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,9 +1,9 @@ -export * from "@/types/ApiResponse"; -export * from "@/types/EmailVerificationToken"; -export * from "@/types/EnrollmentForm/EnrollmentForm"; -export * from "@/types/HealthyHabitsTrackingForm"; -export * from "@/types/PasswordResetToken"; -export * from "@/types/Program"; -export * from "@/types/ProgramEnrollment"; -export * from "@/types/SearchParams"; -export * from "@/types/User"; +export * from "./ApiResponse"; +export * from "./EmailVerificationToken"; +export * from "./EnrollmentForm"; +export * from "./HealthyHabitsTrackingForm"; +export * from "./PasswordResetToken"; +export * from "./Program"; +export * from "./ProgramEnrollment"; +export * from "./SearchParams"; +export * from "./User"; diff --git a/src/utils/authenticateServerFunction.ts b/src/utils/authenticateServerFunction.ts index d8f458d..5f969c3 100644 --- a/src/utils/authenticateServerFunction.ts +++ b/src/utils/authenticateServerFunction.ts @@ -1,8 +1,9 @@ import { Session } from "next-auth"; import { ApiResponse } from "@/types"; -import apiErrors from "@/utils/constants/apiErrors"; -import getUserSession from "@/utils/getUserSession"; + +import apiErrors from "./constants/apiErrors"; +import getUserSession from "./getUserSession"; export default async function authenticateServerFunction( role?: "admin" | "client", diff --git a/src/utils/calculateAge.ts b/src/utils/calculateAge.ts index c6b15dd..675dca0 100644 --- a/src/utils/calculateAge.ts +++ b/src/utils/calculateAge.ts @@ -1,4 +1,4 @@ -import dayjsUtil from "@/utils/dayjsUtil"; +import dayjsUtil from "./dayjsUtil"; export default function calculateAge(dateString: string) { const birthDate = dayjsUtil(dateString, "DD/MM/YYYY"); diff --git a/src/utils/getClosestPastSunday.ts b/src/utils/getClosestPastSunday.ts index 16d3793..85f5e75 100644 --- a/src/utils/getClosestPastSunday.ts +++ b/src/utils/getClosestPastSunday.ts @@ -1,4 +1,4 @@ -import dayjsUtil from "@/utils/dayjsUtil"; +import dayjsUtil from "./dayjsUtil"; export default function getClosestPastSunday() { const today = dayjsUtil(); diff --git a/src/utils/handleMongooseError.ts b/src/utils/handleMongooseError.ts index 95a3c5b..fc2277d 100644 --- a/src/utils/handleMongooseError.ts +++ b/src/utils/handleMongooseError.ts @@ -1,6 +1,6 @@ import mongoose from "mongoose"; -import apiErrors from "@/utils/constants/apiErrors"; +import apiErrors from "./constants/apiErrors"; // hand back specific error messages for Mongoose-related errors export default function handleMongooseError(error: unknown): string {